나는 읽는 시간에 있어서 "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로 끝나는 숫자에는 복수형을 추가 할 수 없다는 것을 알고 있습니다 ...)