我想解析经过的时间(以秒为单位)。时间格式如下:
1) 3 day 18h
2) 3 day
3) 3h 15min
4) 3h
5) 15min 10sec
6) 15min
7) 10sec
我从中获取价值systemctl status cassandra | awk '/(Active: active)/{print $9, $10,$11}'
现在将其值存储在变量 A 中,例如
A=$(systemctl status cassandra | awk '/(Active: active)/{print $9, $10,$11}'
现在 A 输入了 as3 day 18h
或3 day
等。更多示例-
A=3 day 18h or 3 day or 3h 15min or 3h or 15min 10sec or 15min or 10sec
现在采用不同的 A 值,并在几秒钟内进行解析。
答案1
您可以使用date
命令来解析这些值,如下所示:
adjusted_val="$(printf '%s' "$val" | sed 's/h/hour/')"
result="$(date -d "$(date -d @0) + $adjusted_val" +%s)"
奇怪的是,date
它不识别h
(甚至不识别hr
)作为“hour”的缩写,因此,第一步,我们将h
字符串替换为hour
。然后我们通过将@0
(Unix time 0) 扩展为字符串来找到“纪元时间”——Unix 日期/时间计数的日期/时间。 (众所周知,记录为“Jan 1, 1970 00:00:00 GMT”,因此我们可以硬编码该值。)然后我们添加您的字符串:例如,(Jan 1) + 3 day( s) 是 1 月 4 日。然后我们将该+%s
日期/时间显示为 Unix 数字日期/时间,即纪元之后的秒数。这对应于字符串的间隔(增量)值。
如果您想一次执行多个值,您可以通过仅计算一次纪元来优化它:
#!/bin/sh
epoch="$(date -d @0)"
for val
do
adjusted_val="$(printf '%s' "$val" | sed 's/h/hour/')"
if result="$(date -d "$epoch + $adjusted_val" +%s)"
then
printf '%-12s -> %6d\n' "$val" "$result"
else
printf '%-12s <- error\n' "$val"
fi
done
结果:
$ ./myscript '3 day 18h' '3 day' '3h 15min' '3h' '15min 10sec' '15min ' \
'10sec' 'a moment' '3 weeks'
3 day 18h -> 324000
3 day -> 259200
3h 15min -> 11700
3h -> 10800
15min 10sec -> 910
15min -> 900
10sec -> 10
date: invalid date ‘Wed, Dec 31, 1969 7:00:00 PM + a moment’
a moment <- error
3 weeks -> 1814400
请注意,date -d
可以处理“月”一词。如果您有可能获得包含该单词的值,则需要使命令sed
更智能,这样它就不会更改“month”中的“h”。
但是,如果你确实想处理几个月,你应该认真思考“一个月”是什么。例如,我在 2020 年 4 月 12 日写这篇文章。一个月后就是 5 月 12 日——还有 30 天。一个月前是 3 月 12 日,也就是 31 天前。两个月前是2月12日,也就是60(31+29)天前。但是等等,在非闰年中,2 月只有 28 天,因此 2 月 12 日和 4 月 12 日仅相隔 59 天。还有更多:(至少)在美国,2月12日是标准时间,3月12日是夏令时,所以(在非闰年)2月12日中午和3月12日中午只有27天,相隔23小时。情况很复杂。
答案2
我们不能依赖于天和小时参数,因为 7 天后我们将获得周参数,30 天后我们将获得月份参数。
所以最好用Service start time来计算。
#!/bin/bash
SERVICE=cassandra
SERVICE_START_TIME=`systemctl status $SERVICE | awk '/Active: active/{print $6" "$7}'`
SERVICE_UP_TIME=$(($(date +%s) - $(date -d "$SERVICE_START_TIME" +%s)))
echo "$SERVICE uptime : $SERVICE_UP_TIME"
您可以尝试以下一行代码,但我建议使用上面的代码以获得准确的结果。
systemctl status cassandra | awk -F ';' '/Active: active/{print $2}' | sed -e 's/s ago/ 1/; s/s//g; s/min/ 60/; s/h ago/ 3600/; s/day/86400/; s/week/606800/; s/month/2592000/; s/ago//' | awk '{a=$1*$2;b=$3*$4;c=$a+$b;print a" sec"}'