Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 查找三个时间戳之间的差异,这三个时间戳的格式不是date命令所接受的格式_Linux_Bash_Date_Unix_Awk - Fatal编程技术网

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