Linux 查找三个时间戳之间的差异,这三个时间戳的格式不是date命令所接受的格式
我有一个文件,它有三个不同的时间戳,如下所示。我刚才在这里写了两行。该文件有数千行类似的内容Linux 查找三个时间戳之间的差异,这三个时间戳的格式不是date命令所接受的格式,linux,bash,date,unix,awk,Linux,Bash,Date,Unix,Awk,我有一个文件,它有三个不同的时间戳,如下所示。我刚才在这里写了两行。该文件有数千行类似的内容 blah!blah!20190206 12:59:03:579 PM!blah!20190206 12:59:03:691 PM!blah!20190206 12:59:06:422 PM!blah!blah blah!blah!20190206 12:59:06:510 PM!blah!20190206 12:59:06:534 PM!blah!20190206 12:59:06:928 PM!bla
blah!blah!20190206 12:59:03:579 PM!blah!20190206 12:59:03:691 PM!blah!20190206 12:59:06:422 PM!blah!blah
blah!blah!20190206 12:59:06:510 PM!blah!20190206 12:59:06:534 PM!blah!20190206 12:59:06:928 PM!blah!blah
我试图找出每行中每个时间戳之间的差异
使用下面的awk命令
awk -F! 'BEGIN{OFS="!";} {print $3, $5, $7}' | columnt -t -s "!"
我能够像下面这样提取时间戳
20190206 12:59:03:579 PM 20190206 12:59:03:691 PM 20190206 12:59:06:422 PM
20190206 12:59:06:510 PM 20190206 12:59:06:534 PM 20190206 12:59:06:928 PM
现在,第一个问题是这些时间戳的格式不适合传递给date命令
$ date -d "20190206 12:59:06:510 PM" +%s
date: invalid date '20190206 12:59:06:510 PM'
$ date -d "20190206 12:59:06,510 PM" +%s+%3N
1550080746+510
$
$ date -d "20190206 12:59:06,536 PM" +%s+%3N
1550080746+536
$
$ echo $(( `date -d "20190206 12:59:06,510 PM" +%s+%3N` - `date -d "20190206 12:59:06,536 PM" +%s+%3N` ))
$ 1046
$
第三个冒号需要用逗号替换,以便传递给date命令
$ date -d "20190206 12:59:06:510 PM" +%s
date: invalid date '20190206 12:59:06:510 PM'
$ date -d "20190206 12:59:06,510 PM" +%s+%3N
1550080746+510
$
$ date -d "20190206 12:59:06,536 PM" +%s+%3N
1550080746+536
$
$ echo $(( `date -d "20190206 12:59:06,510 PM" +%s+%3N` - `date -d "20190206 12:59:06,536 PM" +%s+%3N` ))
$ 1046
$
第二,我如何得到下面这样的输出,以及与时间戳一起打印的每行时间戳之间的差异。因此,我可以浏览输出,找出哪一行花费的时间更多
20190206 12:59:03:579 PM 20190206 12:59:03:691 PM 20190206 12:59:06:422 PM
(difference between first and second column) (difference between second and third column)
20190206 12:59:06:510 PM 20190206 12:59:06:534 PM 20190206 12:59:06:928 PM
(difference between first and second column) (difference between second and third column)
20190206 12:59:03:579 PM 20190206 12:59:03:691 PM 20190206 12:59:06:422 PM
112 milliseconds 2731 milliseconds
20190206 12:59:06:510 PM 20190206 12:59:06:534 PM 20190206 12:59:06:928 PM
24 milliseconds 394 milliseconds
如果date无法读取输入,请使用sed将输入格式化为它可以读取的格式
cat <<EOF >file
blah!blah!20190206 12:59:03:579 PM!blah!20190206 12:59:03:691 PM!blah!20190206 12:59:06:422 PM!blah!blah
blah!blah!20190206 12:59:06:510 PM!blah!20190206 12:59:06:534 PM!blah!20190206 12:59:06:928 PM!blah!blah
EOF
# remove the blah! words to leave only timestamps
# so we have: '20190206 12:59:03:579 PM!20190206 12:59:03:691 PM!20190206 12:59:06:422 PM'
<file cut -d'!' -f3,5,7
# substitute the parts ':123 ' into '.123 ' so that date knows it's miliseconds
# now we have '20190206 12:59:03.579 PM!20190206 12:59:03.691 PM!20190206 12:59:06.422 PM'
sed 's/:\([0-9]\{3\} \)/.\1/g' |
# read the dates - they are still separated by `!`
while IFS='!' read -r d1 d2 d3; do
# convert dates into seconds since epoch
s1=$(date --date="$d1" +%s.%N)
s2=$(date --date="$d2" +%s.%N)
s3=$(date --date="$d3" +%s.%N)
# compute differences
diff21=$(bc <<<"scale=100; $s2 - $s1")
diff32=$(bc <<<"scale=100; $s3 - $s2")
# nice looking printf - I leave it to OP to extract only miliseconds and such
printf "%.3f %.3f\n" "$diff21" "$diff32"
done
最后,我对xargs很感兴趣,这里使用xargs也是一样的:
而且它看起来更整洁。带有GNU awk的时间函数:
$ cat tst.awk
BEGIN { FS="!"; OFS=" " }
{
numTs = 0
for (i=3; i<=7; i+=2) {
split($i,t,/[[:space:]:]/)
date = gensub(/(.{4})(.{2})/,"\\1 \\2 ",1,t[1])
time = ( t[2] + ( (t[6] == "PM") && (t[2] < 12) ? 12 : 0 ) ) " " t[3] " " t[4]
secs = mktime(date " " time)
ts[++numTs] = $i
ms[numTs] = (secs * 1000) + t[5]
}
print ts[1], ts[2], ts[3]
print " " (ms[2] - ms[1]) " milliseconds", (ms[3] - ms[2]) " milliseconds"
}
$ awk -f tst.awk file
20190206 12:59:03:579 PM 20190206 12:59:03:691 PM 20190206 12:59:06:422 PM
112 milliseconds 2731 milliseconds
20190206 12:59:06:510 PM 20190206 12:59:06:534 PM 20190206 12:59:06:928 PM
24 milliseconds 394 milliseconds
不错,虽然这可能可以归结为大约六行GNU Awk,它有一个方便的输出,请检查预期输出中的毫秒值。它们要么是错误的,需要纠正,要么你需要解释这些值是如何推导出来的。有可能在几秒钟内得到输出吗?就像Kamil CukYes给出的答案一样,它很琐碎,我不认为代码太难阅读,以至于在思考几秒钟后,你就不知道如何为自己做到这一点。试一试,如果你有任何问题,请提问。
$ cat tst.awk
BEGIN { FS="!"; OFS=" " }
{
numTs = 0
for (i=3; i<=7; i+=2) {
split($i,t,/[[:space:]:]/)
date = gensub(/(.{4})(.{2})/,"\\1 \\2 ",1,t[1])
time = ( t[2] + ( (t[6] == "PM") && (t[2] < 12) ? 12 : 0 ) ) " " t[3] " " t[4]
secs = mktime(date " " time)
ts[++numTs] = $i
ms[numTs] = (secs * 1000) + t[5]
}
print ts[1], ts[2], ts[3]
print " " (ms[2] - ms[1]) " milliseconds", (ms[3] - ms[2]) " milliseconds"
}
$ awk -f tst.awk file
20190206 12:59:03:579 PM 20190206 12:59:03:691 PM 20190206 12:59:06:422 PM
112 milliseconds 2731 milliseconds
20190206 12:59:06:510 PM 20190206 12:59:06:534 PM 20190206 12:59:06:928 PM
24 milliseconds 394 milliseconds