Linux awk/bash比较时间戳和跨行排序时间差

Linux awk/bash比较时间戳和跨行排序时间差,linux,bash,shell,awk,Linux,Bash,Shell,Awk,我有这样一个日志文件: 2019-10-15 13:35:46.823 INFO : xxx 2019-10-15 13:35:46.886 INFO : yyy 2019-10-15 13:35:46.943 INFO : zzz 2019-10-15 13:35:47.822 INFO : aaa 2019-10-15 13:35:48.824 INFO : bbb 我需要找出连续行的时间戳之间的时间差(毫秒),并按时间差排序(忽略第一行) 我可以通过编写bash脚本来做到这一点,比如 l

我有这样一个日志文件:

2019-10-15 13:35:46.823 INFO : xxx
2019-10-15 13:35:46.886 INFO : yyy
2019-10-15 13:35:46.943 INFO : zzz
2019-10-15 13:35:47.822 INFO : aaa
2019-10-15 13:35:48.824 INFO : bbb
我需要找出连续行的时间戳之间的时间差(毫秒),并按时间差排序(忽略第一行)

我可以通过编写bash脚本来做到这一点,比如

lastEpoch=0
while read p; do
  logTime=$(echo $p | cut -c1-24)
  currentEpoch=$(date -d "$logTime" +%s%3N)
  log="$log $logTime$((currentEpoch-$lastEpoch))"$'\n'
  lastEpoch=$currentEpoch  
done < my.log
echo -e "$log" > tmp.log
sort -nrk3 tmp.log
lastpoch=0
读p;做
对数时间=$(回声$p切-c1-24)
currentEpoch=$(日期-d“$logTime”+%s%3N)
log=“$log$logTime$((当前历元-$lastEpoch))”$”\n
lastpoch=$currentpoch
完成<我的日志
echo-e“$log”>tmp.log
排序-nrk3 tmp.log
但是运行脚本需要很长的时间,因为我的原始日志文件有1百万行,我想我没有使用最有效的方法来实现这一点


我认为awk可以有效地做到这一点,但我对awk非常陌生,有人能给我一些关于如何在awk上做到这一点的提示吗。。?或者有更有效的方法吗?

您可以在bash中执行此操作,并在读取时使用
循环和
日期将日期转换为秒,然后从以前的值中减去日期并打印。但是,正如您所发现的,为每行调用
date
非常非常慢

可以使用
mktime
函数在
awk
中计算差异,但您必须首先将其转换为
mktime
可以吃的格式。然后分类

awk '{
    match($1 " " $2, /([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+):([0-9]+)\.([0-9]+)/, t)
    now = mktime(t[1] " " t[2] " " t[3] " " t[4] " " t[5] " " t[6]) * 1000 + t[7] 
    diff = now - prev
    prev = now
    print $1 " " $2 " " diff
}' | sort -r -n -k3

你能试试下面的吗

awk -F' INFO|: ' '
{
  split($1,array,"[- :.]")
  current=mktime(array[1] " " array[2] " " array[3] " " array[4] " " array[5] " " array[6]) * 1000 + array[7]
  print $1,$2,current-prev
  prev=current
}
' Input_file  | sort -r -nk3

我会在不排序的情况下运行脚本,看看它会持续多长时间,以便知道是排序操作很繁重还是日期转换。我想知道您的代码
$($currentEpoch-$lastEpoch))
不应该是
$($currentEpoch-$lastEpoch))
(注意“$”在bash表达式的开头签名。@Pierrefransois是的,缺少$,不知道为什么脚本在这种情况下仍然有效我刚刚发现在bash表达式中,'$'的存在不是强制性的。因此,如果
a=2;b=5
您可以发出
echo$($a+$b))
以及
echo$((a+b))
awk -F' INFO|: ' '
{
  split($1,array,"[- :.]")
  current=mktime(array[1] " " array[2] " " array[3] " " array[4] " " array[5] " " array[6]) * 1000 + array[7]
  print $1,$2,current-prev
  prev=current
}
' Input_file  | sort -r -nk3