将星号正常运行时间字符串转换为日期
Convert asterisk uptime string to date
如何将 "System uptime: 2 days, 9 hours, 16 minutes, 5 seconds" 转换为 bash 日期?
我想将这个日期与另一个日期进行比较。
提前致谢。
请注意,uptime
命令从 /proc/uptime
获取数据
所以一种方法是获取第一个字段值,即以秒为单位的总运行时间,并将其提供给 date
命令:-
这里有一个例子:-
$ cat /proc/uptime
8743161.15 7738916.50
$ date -d'-8743161.15 seconds'
Sat Jul 6 06:00:37 EDT 2019
假设消息将始终包含固定位置的所有日期组件,可以使用 Unix 时间戳(纪元后的秒数)计算。
# Set t from command, or file.
t="System uptime: 2 days, 9 hours, 16 minutes, 5 seconds"
# Split into words
read -a p <<< "$t"
# Uptime in seconds
uptime=$((p[2]*24*60*60+p[4]*60*60+p[6]*60+p[8]))
now=$(date '+%s')
up_ts=$((now-uptime))
echo "Timestamp: $up_ts"
# Convert to human readable date.
up_date=$(date +'%Y-%m-%d %H:%M:%S' -d "@$up_ts")
echo "Date: $up_date"
您还可以在 'up_ts' 上使用 bash 内置日期格式。
如果正常运行时间消息的格式取决于值(例如,如果正常运行时间 < 1 天,则不包括天数),则需要进行额外的解析。
在这里,您会发现一种可靠的方法,可以将您的持续时间转换为总秒数。这是稳健的,因为它不需要列出所有数量。 IE。输出可以是以下任何一种:
System uptime: 16 minutes, 2 seconds
System uptime: 12 days, 3 seconds
System uptime: 15minutes,12hours
创建一个包含
的文件convert.awk
BEGIN { a["seconds"]=1; a["minutes"]=60
a["hours"]=3600; a["days"]=86400;
a["weeks"]=7*86400 }
{ tmp=tolower([=11=]) }
{ while (match(tmp,/[0-9]+[^a-z]*[a-z]+/)) {
u=substr(tmp,RSTART,RLENGTH); q=u+0; gsub(/[^a-z]/,"",u)
t+=q*a[u]
tmp=substr(tmp,RSTART+RLENGTH)
}
print t
}
运行以下命令:
$ echo "System uptime: 2 days, 9 hours, 16 minutes, 5 seconds" | awk -f convert.awk
206165
$ echo "System uptime: 2 weeks, 9 days, 16 minutes, 5 seconds" | awk -f convert.awk
1988165
这是如何工作的:
当我们读一行时,例如
tmp="system uptime: 16 minutes, 2 seconds"
match
命令将搜索任何以数字开头并以字符串结尾的子字符串。 match
会自动将变量 RSTART
和 RLENGTH
设置为找到的子字符串的位置及其长度。这样,命令 u=substr(tmp,RSTART,RLENGTH)
将设置
u="16 minutes"
您现在可以对此进行运算,提取第一个数字。这适用于 awk,因为它会通过忽略后面的任何内容将任何以数字开头的字符串转换为数字。所以 q=u+0
创建
q=16
最后,我们从 u
中删除任何不是字符的内容,导致
u="minutes"
下一步我们通过删除我们已经处理的任何内容来重新定义 tmp
。
tmp=", 2 seconds"
然后重新开始这个过程。
如何将 "System uptime: 2 days, 9 hours, 16 minutes, 5 seconds" 转换为 bash 日期?
我想将这个日期与另一个日期进行比较。
提前致谢。
请注意,uptime
命令从 /proc/uptime
所以一种方法是获取第一个字段值,即以秒为单位的总运行时间,并将其提供给 date
命令:-
这里有一个例子:-
$ cat /proc/uptime
8743161.15 7738916.50
$ date -d'-8743161.15 seconds'
Sat Jul 6 06:00:37 EDT 2019
假设消息将始终包含固定位置的所有日期组件,可以使用 Unix 时间戳(纪元后的秒数)计算。
# Set t from command, or file.
t="System uptime: 2 days, 9 hours, 16 minutes, 5 seconds"
# Split into words
read -a p <<< "$t"
# Uptime in seconds
uptime=$((p[2]*24*60*60+p[4]*60*60+p[6]*60+p[8]))
now=$(date '+%s')
up_ts=$((now-uptime))
echo "Timestamp: $up_ts"
# Convert to human readable date.
up_date=$(date +'%Y-%m-%d %H:%M:%S' -d "@$up_ts")
echo "Date: $up_date"
您还可以在 'up_ts' 上使用 bash 内置日期格式。
如果正常运行时间消息的格式取决于值(例如,如果正常运行时间 < 1 天,则不包括天数),则需要进行额外的解析。
在这里,您会发现一种可靠的方法,可以将您的持续时间转换为总秒数。这是稳健的,因为它不需要列出所有数量。 IE。输出可以是以下任何一种:
System uptime: 16 minutes, 2 seconds
System uptime: 12 days, 3 seconds
System uptime: 15minutes,12hours
创建一个包含
的文件convert.awk
BEGIN { a["seconds"]=1; a["minutes"]=60 a["hours"]=3600; a["days"]=86400; a["weeks"]=7*86400 } { tmp=tolower([=11=]) } { while (match(tmp,/[0-9]+[^a-z]*[a-z]+/)) { u=substr(tmp,RSTART,RLENGTH); q=u+0; gsub(/[^a-z]/,"",u) t+=q*a[u] tmp=substr(tmp,RSTART+RLENGTH) } print t }
运行以下命令:
$ echo "System uptime: 2 days, 9 hours, 16 minutes, 5 seconds" | awk -f convert.awk 206165 $ echo "System uptime: 2 weeks, 9 days, 16 minutes, 5 seconds" | awk -f convert.awk 1988165
这是如何工作的:
当我们读一行时,例如
tmp="system uptime: 16 minutes, 2 seconds"
match
命令将搜索任何以数字开头并以字符串结尾的子字符串。 match
会自动将变量 RSTART
和 RLENGTH
设置为找到的子字符串的位置及其长度。这样,命令 u=substr(tmp,RSTART,RLENGTH)
将设置
u="16 minutes"
您现在可以对此进行运算,提取第一个数字。这适用于 awk,因为它会通过忽略后面的任何内容将任何以数字开头的字符串转换为数字。所以 q=u+0
创建
q=16
最后,我们从 u
中删除任何不是字符的内容,导致
u="minutes"
下一步我们通过删除我们已经处理的任何内容来重新定义 tmp
。
tmp=", 2 seconds"
然后重新开始这个过程。