如何清理日志文件以仅显示一次连续重复的行,并用一个数字指示该行重复的次数?

如何清理日志文件以仅显示一次连续重复的行,并用一个数字指示该行重复的次数?

当前日志:

18:56:54 Info: Starting
18:56:55 Error: timed out
18:56:56 Error: timed out
18:56:57 Error: timed out
18:56:58 Info: reconnected
18:56:59 Error: timed out

期望的输出:

18:56:54 Info: Starting
18:56:55 Error: timed out (3)
18:56:57 Info: reconnected
18:56:58 Error: timed out

我的日志文件可能有数千个重复行,我想使用 bash/linux 命令复制 chrome 日志的行为。

我发现这个,很接近: 删除部分重复的连续行,但保留第一行和最后一行

它给出了这个神奇的 awk 命令:

awk '{n=$2$3$4$5$6$7}l1!=n{if(p)print l0; print; p=0}l1==n{p=1}{l0=$0; l1=n}END{print}' file

(至关重要的是,排除 n=$1 允许时间戳不同,这是必需的。显示压缩行的确切时间戳并不重要。)

但我还需要添加一个计数器,所以我清楚地知道删除了什么,在可读性和准确性之间做出了适当的妥协(唯一丢失的信息将是重复消息的确切时间,有第一个或最后一个时间戳就足够了。 )

谢谢,我不擅长 awk,刚刚了解了 uniq,希望有人可以将我链接到解决方案,或者将其视为一个有趣的练习。干杯。

答案1

不需要awk,直接使用即可uniq

uniq -c -f 1 file

-c选项给出了在输入中连续找到一行的次数,并且您可以使用 跳过第一个空格或制表符分隔字段中的时间戳-f 1

给出问题中数据的示例:

$ uniq -c -f 1 file
   1 18:56:54 Info: Starting
   3 18:56:55 Error: timed out
   1 18:56:58 Info: reconnected
   1 18:56:59 Error: timed out

答案2

如果您对行开头的计数感到满意,uniq那么您所需要的就是:

$ uniq -f 1 -c log.txt 
      1 18:56:54 Info: Starting
      3 18:56:55 Error: timed out
      1 18:56:58 Info: reconnected
      1 18:56:59 Error: timed outhet

-f 1跳过第一个字段,-c计算行数。

要获得您要求的确切格式,您需要处理uniq的输出,例如sed

$ uniq -f1 -c log.txt | 
    sed -E -e 's/^[[:space:]]+//;
               s/^([[:digit:]]+)[[:space:]]+(.*)/\2 (\1)/;
               s/ \(1\)$//' 
18:56:54 Info: Starting
18:56:55 Error: timed out (3)
18:56:58 Info: reconnected
18:56:59 Error: timed out

sed 脚本使用扩展正则表达式(-E选项)又名 ERE,而不是默认的基本正则表达式 (BRE) 并且:

  • 去除每行的前导空格
  • 将每行开头的所有数字移动到行尾,用括号括起来
  • 从每行末尾删除“(1)”(如果存在)。

答案3

使用 awk实用程序我们可以得出事件的唯一计数,如下所示:

$ awk '
{t=substr($0,1+index($0,FS))}
prev != t {
  if (NR>1) {fx(line,knt)}
  knt = 0
  prev = t
}{
  line = $0
  knt++
}
END {fx(line,knt)}
function fx(a,b) {
  print a (b>1?sprintf("%s(%d)",OFS,b):"")
}
' file
18:56:54 Info: Starting
18:56:57 Error: timed out (3)
18:56:58 Info: reconnected
18:56:59 Error: timed out

笔记:-

  • 假设没有前导空格/没有连续空格。

答案4

命令

uniq -f 1 -c filename| awk '{print $2,$3,$4,$5,$1}'| awk '{if($NF > 1){$NF="("$NF")";print }else{$NF="";print }}'

输出

18:56:54 Info: Starting 
18:56:55 Error: timed out (3)
18:56:58 Info: reconnected 
18:56:59 Error: timed out 

相关内容