Bash: 여러 변수 중 하나만 동일한지 확인하세요.

Bash: 여러 변수 중 하나만 동일한지 확인하세요.

나는 읽는 시간에 있어서 "and"의 형식을 올바르게 지정하려고 노력하고 있습니다. 마지막 값(시간, 분 또는 초) 이전과 여러 값이 있는 경우에만 "and"를 에코하는 방법을 알아내려고 합니다(두 개의 값이 필요합니다. 즉: 2일과 5일). 분 또는 2일 12시간 5분)

올바른 구문을 모르겠습니다. H, M, S 중 하나의 값만 0보다 크면 $DAnd="and "입니다. 이것도 몇시간씩 반복되기 때문에 M과 S만 0보다 큰 값이 있으면 "$HAnd="and"가 됩니다. 몇 분 안에 S가 0보다 큰지만 확인하기 때문에 쉽습니다.

많은 코드를 작성하지 않고 어떻게 이를 달성할 수 있습니까?

내 현재 스크립트:

#!/bin/bash
TIME1="08/15/2018 10:30:41"
TIME2="08/30/2018 8:34:40"
SEC1=`date +%s -d "${TIME1}"`
SEC2=`date +%s -d "${TIME2}"`
DIFF=`expr ${SEC2} - ${SEC1}`
CONVERTTIME()
{
  local T=$1
  local D=$((T/60/60/24))
  local H=$((T/60/60%24))
  local M=$((T/60%60))
  local S=$((T%60))
  if [[ $D > 0 ]]; then
    [[ ($H = 0 || $M = 0 || $S = 0) && ($H = 0 && $M = 0 && $S = 0) ]] && DComma="" || DComma=","
    #The problem
    [[ ($H > 0 || $M > 0 || $S > 0) && ($H = 0 || $M = 0 || $S = 0) ]] && DAnd="" || DAnd="and "
    [[ $D = 1 ]] && echo -n "$D day$DComma " || echo -n "$D days$DComma $DAnd"

  fi
  if [[ $H > 0 ]]; then
    [[ ($M = 0 || $S = 0) && ($M = 0 && $S = 0) ]] && HComma="" || HComma=","
    #The problem
    [[ ($M > 0 || $S > 0) && ($M = 0 || $S = 0) ]] && HAnd="" || HAnd="and "
    [[ $H = 1 ]] && echo -n "$H hour$HComma $HAnd" || echo -n "$H hours$HComma $HAnd"
  fi
  if [[ $M > 0 ]]; then
    [[ $S = 0 ]] && MComma="" || MComma=", and "
    [[ $M = 1 ]] && echo -n "$M minute$MComma" || echo -n "$M minutes$MComma"
  fi
  if [[ $S > 0 ]]; then
    [[ $S = 0 ]] && echo -n "$S second" || echo -n "$S seconds"
  fi
  # If no difference in time:
  [[ $D = 0 && $H = 0 && $M = 0 && $S = 0 ]] && echo -n "0 seconds"
  echo
}
echo
echo "TIME DIFFERENCE: $(CONVERTTIME $DIFF)"
echo

답변1

와 같이 쓰겠습니다

seconds2text() {     
    local diff=$1
    local words=()
    if (( diff == 0 )); then
        words=("0 seconds")
    else
        local s=$((diff % 60))
        local m=$((diff / 60 % 60))
        local h=$((diff / 60 / 60 % 24))
        local d=$((diff / 60 / 60 / 24))

        (( d > 0 )) && { unit=day;    (( d > 1 )) && unit+=s; words+=("$d $unit"); };
        (( h > 0 )) && { unit=hour;   (( h > 1 )) && unit+=s; words+=("$h $unit"); }
        (( m > 0 )) && { unit=minute; (( m > 1 )) && unit+=s; words+=("$m $unit"); }
        (( s > 0 )) && { unit=second; (( s > 1 )) && unit+=s; words+=("$s $unit"); }
        (( ${#words[@]} > 1 )) && words[-1]="and ${words[-1]}"
    fi
    local IFS=,
    local text="${words[*]}"
    text=${text/,and/ and}
    echo "${text//,/, }"
}

그런 다음

$ for d in 0 1 61 3600 3601 3660 3661 86400 86401 86460 86461 90000 90001 90060 90061 180122; do seconds2text $d; done
0 seconds
1 second
1 minute and 1 second
1 hour
1 hour and 1 second
1 hour and 1 minute
1 hour, 1 minute and 1 second
1 day
1 day and 1 second
1 day and 1 minute
1 day, 1 minute and 1 second
1 day and 1 hour
1 day, 1 hour and 1 second
1 day, 1 hour and 1 minute
1 day, 1 hour, 1 minute and 1 second
2 days, 2 hours, 2 minutes and 2 seconds

노트:

  • [[ $x > 0 ]]그리고 [[ $x = 0 ]]하고있다비교해봐, 아니숫자비교하다. 대신 ((x > 0))and를 사용하세요 ((x == 0))( $여기서는 필요하지 않습니다).
  • 변수를 모두 대문자로 사용하는 습관을 버리십시오. 빵 껍질을 위해 남겨주세요. 어느 날 당신은 PATH=something글쓰기를 마치고 왜 당신의 대본이 망가졌는지 궁금해하게 될 것입니다.

답변2

그리고 zsh:

#! /bin/zsh -
t1=${1?first date please}
t2=${2?second date please}

zmodload zsh/datetime
strftime -rst1 '%m/%d/%Y %H:%M:%S' "$t1" || exit
strftime -rst2 '%m/%d/%Y %H:%M:%S' "$t2" || exit

t=$((t2 - t1))
if ((t)) {
  and=' and' out= plural=s
  for unit duration (
    second 60
    minute 60
    hour   24
    day    7
    week   t+1
  ) {
    ((n = t % duration))
    ((t /= duration))
    ((n > 0)) && out="$and $n $unit${plural: n<2}$out" and=,
    ((t)) || break
  }
  out=${out#?* }
} else {
  out=now
}
echo "$out"

그 다음에:

./that-script "08/15/2018 10:30:41" "08/30/2018 8:34:40"
2 weeks, 22 hours, 3 minutes and 59 seconds

답변3

date명령을 sed스크립트(날짜/시간 차이가 1년 미만) 와 결합하려면 어떻게 해야 합니까 ? 노력하다

date +"%j d, %H h, %M m, %S s" -d@$(((d-90000))) | sed -r 's/, 0*00 .//g; s/365 d,* *//; s/ ([0-9]{2} [dhms])$/ and \1/; s/(^| )0+/\1/g; s/^$/0 s/; s/([02-9] [dhms])/\1s/g; s/ d(s|,|$)/ day\1/; s/ h/ hour/; s/ m/ minute/; s/ s/ second/'

Glenn jackman의 게시물에서 테스트 루프를 훔칩니다.

for DIFF in 0 1 61 3600 3601 3660 3661 86400 86401 86460 86461 90000 90001 90060 90061 180122
  do date +"%j d, %H h, %M m, %S s" -d@$(((DIFF-90000))) |
sed -r '
s/, 0*00 .//g
s/365 d,* *//
s/ ([0-9]{2} [dhms])$/ and \1/
s/(^| )0+/\1/g
s/^$/0 s/
s/([02-9] [dhms])/\1s/g
s/ d(s|,|$)/ day\1/
s/ h/ hour/
s/ m/ minute/
s/ s/ second/
'; done
0 seconds
1 second
1 minute, and 1 second
1 hour
1 hour, and 1 second
1 hour, and 1 minute
1 hour, 1 minute, and 1 second
1 day
1 day, and 1 second
1 day, and 1 minute
1 day, 1 minute, and 1 second
1 day, and 1 hour
1 day, 1 hour, and 1 second
1 day, 1 hour, and 1 minute
1 day, 1 hour, 1 minute, and 1 second
2 days, 2 hours, 2 minutes, and 2 seconds

s( 11, 21 등과 같이 1로 끝나는 숫자에는 복수형을 추가 할 수 없다는 것을 알고 있습니다 ...)

관련 정보