bash中的时间戳算法

时间:2012-01-17 00:45:40

标签: bash date awk unix-timestamp iso8601

假设我有两个日志文件(input.logoutput.log),格式如下:

2012-01-16T12:00:00 12345678

第一个字段是处理时间戳,第二个字段是唯一ID。我试图找到:

  1. 来自input.log的记录output.log
  2. 中没有该ID的相应记录
  3. 来自input.log的记录包含该ID的记录,时间戳的差异超过5秒
  4. 我有一个workaround solution with MySQL,但我最好删除数据库组件并使用shell脚本处理它。

    我有以下内容,如果input.log包含ID,则会返回output.log行并添加一列:

    join -a1 -j2 -o 0 1.1 2.1 <(sort -k2,2 input.log) <(sort -k2,2 output.log)
    

    示例输出:

    10111 2012-01-16T10:00:00 2012-01-16T10:00:04
    11562 2012-01-16T11:00:00 2012-01-16T11:00:10
    97554 2012-01-16T09:00:00
    

    主要问题

    现在我已经掌握了这些信息,我该如何计算两个时间戳之间的差异并丢弃相隔超过5秒的时间戳?我在处理带有date的ISO 8601时间戳(特别是T)时遇到了一些问题,并假设必须有更好的方法。

    次要问题

    是否有可能重新编写整个方法,例如单个awk脚本?我对处理多个文件以及为输出条件设置正确的不等式的知识是限制因素,因此采用上述方法。

3 个答案:

答案 0 :(得分:4)

如果您有GNU awk,那么您可以尝试这样的事情 -

gawk '
NR==FNR{a[$2]=$1;next} 
!($2 in a) {print $2,$1; next} 
($2 in a) {
  "date +%s -d " $1 | getline var1;
  "date +%s -d " a[$2] | getline var2;
  var3 = var2 - var1;
  if (var3 > 4) print $2, $1, a[$2]
}' output.log input.log

测试:

[jaypal:~/Temp] cat input.log 
2012-01-16T09:00:00 9
2012-01-16T10:00:00 10
2012-01-16T11:00:00 11

[jaypal:~/Temp] cat output.log 
2012-01-16T10:00:04 10
2012-01-16T11:00:10 11
2012-01-16T12:00:00 12

[jaypal:~/Temp] gawk '
NR==FNR{a[$2]=$1;next} 
!($2 in a) {print $2,$1; next} 
($2 in a) {"date +%s -d " $1 | getline var1; "date +%s -d " a[$2] | getline var2;var3=var2-var1;if (var3>4) print $2,$1,a[$2] }' output.log input.log
9 2012-01-16T09:00:00
11 2012-01-16T11:00:00 2012-01-16T11:00:10

说明:

  • NR==FNR{a[$2]=$1;next}

我们首先将output.log文件中的第一个字段存储在第二个字段上索引的数组中。我们使用next来阻止其他pattern{action}语句运行。使用NR==FNR允许我们完全填充output.log文件。

  • !($2 in a) {print $2,$1; next}

完成output.log文件后。我们从input.log文件开始。我们检查input.log文件中是否存在任何第二个字段在我们的数组中(即output.log文件)。如果发现我们打印它。我们继续这一行动,直到我们打印出所有这些字段。

  • ($2 in a) {"date +%s -d " $1 | getline var1; "date +%s -d " a[$2] | getline var2; var3=var2-var1; if (var3 > 4) print $2,$1,a[$2] }

在此我们会查找两个文件中 的字段。当我们找到这些字段时,我们需要输入逻辑来计算差异。我们使用system命令查找日期。现在系统命令默认打印到STDOUT,我们无法控制它们。因此,我们使用awk getline函数管道输出并捕获输出,并将其存储在变量(var1和var2)中。一旦两个日期都存储在变量中,我们就会做差异并存储在var3中,如果发现var3是&gt; 4,我们以您想要的格式打印它。

答案 1 :(得分:2)

以下是我采用的解决方案:

cat input.log
2012-01-16T09:00:00 9
2012-01-16T10:00:00 10
2012-01-16T11:00:00 11

cat output.log
2012-01-16T10:00:04 10
2012-01-16T11:00:10 11
2012-01-16T12:00:00 12

sort -k2,2 input.log > input.sort
sort -k2,2 output.log > output.sort

join -a1 -j2 -o 0 1.1 2.1 input.sort output.sort | while read id i o; do
    if [ -n "$o" ]; then
        ot=$(date +%s -d "${o/T/ }")
        it=$(date +%s -d "${i/T/ }")
        [[ $it+5 -lt $ot ]] && echo $id $i $o
    else echo $id $i
    fi
done
11 2012-01-16T11:00:00 2012-01-16T11:00:10
9 2012-01-16T09:00:00

答案 2 :(得分:-1)

t1=2012-01-16T10:00:00
t2=2012-01-16T10:00:04
echo $(($(date -d $t1 +%s)-$(date -d $t2 +%s)))
-4