5

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

2012-01-16T12:00:00 12345678

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

  1. input.log中没有该 ID 对应记录的记录output.log
  2. input.log具有该 ID 记录但时间戳差异超过 5 秒的记录

我有一个MySQL 的解决方案,但理想情况下我想删除数据库组件并使用 shell 脚本处理它。

我有以下内容,如果包含 ID ,则返回input.log带有添加列的行: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

主要问题

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

次要问题

有没有办法重新设计整个方法,例如变成一个awk脚本?我对处理多个文件和为输出条件设置正确不等式的知识是这里的限制因素,因此采用了上述方法。

4

3 回答 3

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] }

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

于 2012-01-17T07:34:18.850 回答
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
于 2012-01-17T02:47:45.090 回答
-1
t1=2012-01-16T10:00:00
t2=2012-01-16T10:00:04
echo $(($(date -d $t1 +%s)-$(date -d $t2 +%s)))
-4
于 2012-01-17T03:01:05.517 回答