当谈到阅读时间时,我正在尝试正确格式化“和”。我想尝试弄清楚如何仅在最后一个值(无论是小时、分钟还是秒)之前回显“和”,并且仅当有多个值时(需要两个值,即: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
脚本结合起来(日期/时间差异小于一年)?尝试
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
在任何以 1 结尾的数字上添加复数,例如 11、21 等...)