1

如果超过 X 个字符,系统会在日志文件中换行。我正在尝试从日志中提取各种数据,但首先我需要合并所有分割线,以便 gawk 可以将字段解析为单个记录。

例如:

2012/11/01 field1 field2 field3 field4 fi
eld5 field6 field7
2012/11/03 field1 field2 field3
2012/12/31 field1 field2 field3 field4 fi
eld5 field6 field7 field8 field9 field10 
field11 field12 field13
2013/01/10 field1 field2 field3
2013/01/11 field1 field2 field3 field4

我想回来

2012/11/01 field1 field2 field3 field4 field5 field6 field7
2012/11/03 field1 field2 field3
2012/12/31 field1 field2 field3 field4 field5 field6 field7 field8 field9 field10 field11 field12 field13
2013/01/10 field1 field2 field3
2013/01/11 field1 field2 field3 field4

在我的情况下,实际的最大行长度是 130。我不愿意测试该长度并用于getline加入下一行,以防有一个正好 130 个字符长的条目。

清理完日志文件后,我还想提取所有相关事件,其中“相关”可能涉及以下标准:

  • 'foo' 位于记录中任何字段的任何位置
  • 字段2 ~ /bar| dtn /
  • 如果field1 ~ /xyz|abc/ && field98 == "0001"

我想知道是否需要运行两个连续的 gawk 程序,或者是否可以将所有这些程序合并为一个。

我是一个笨拙的新手,来自非 Unix

4

6 回答 6

2
gawk '{ gsub( "\n", "" ); printf $0 RT }
    END { print }' RS='\n[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]' input

这可以通过以下方式稍微简化:

gawk --re-interval '{ gsub( "\n", "" ); printf $0 RT }
    END { print }' RS='\n[0-9]{4}/[0-9]{2}/[0-9]{2}' input
于 2013-02-08T20:36:13.260 回答
2

这可能对您有用(GNU sed):

sed -r ':a;$!N;\#\n[0-9]{4}/[0-9]{2}/[0-9]{2}#!{s/\n//;ta};P;D' file
于 2013-02-08T23:20:26.833 回答
2
$ awk '{printf "%s%s",($1 ~ "/" ? rs : ""),$0; rs=RS} END{print ""}' file
2012/11/01 field1 field2 field3 field4 field5 field6 field7
2012/11/03 field1 field2 field3
2012/12/31 field1 field2 field3 field4 field5 field6 field7 field8 field9 field10 field11  field12 field13
2013/01/10 field1 field2 field3
2013/01/11 field1 field2 field3 field4

现在我注意到您实际上并不想只打印重新组合的记录,这是另一种方法,它更适合在重新编译的记录上进行测试(此脚本中的“s”:

$ awk 'NR>1 && $1~"/"{print s; s=""} {s=s $0} END{print s}' file

现在有了这个结构,您可以对 s 执行测试,而不是仅仅打印 s,例如(注意第三条记录中的“foo”):

$ cat file
2012/11/01 field1 field2 field3 field4 fi
eld5 field6 field7
2012/11/03 field1 field2 field3
2012/12/31 field1 field2 foo field4 fi
eld5 field6 field7 field8 field9 field10
field11 field12 field13
2013/01/10 field1 field2 field3
2013/01/11 field1 field2 field3 field4

$ awk '
function tst(rec,     flds,nf,i) {
   nf=split(rec,flds)
   if (rec ~ "foo") {
      print rec
      for (i=1;i<=nf;i++)
         print "\t",i,flds[i]
   }
}
NR>1 && $1~"/" { tst(s); s="" }
{ s=s $0 }
END { tst(s) }
' file
2012/12/31 field1 field2 foo field4 field5 field6 field7 field8 field9 field10 field11 field12 field13
         1 2012/12/31
         2 field1
         3 field2
         4 foo
         5 field4
         6 field5
         7 field6
         8 field7
         9 field8
         10 field9
         11 field10
         12 field11
         13 field12
         14 field13
于 2013-02-09T00:16:19.387 回答
1

这是一个稍微大一点的 Perl 解决方案,它还处理额外的过滤(正如您也标记了这个perl):

root@virtualdeb:~# cat combine_and_filter.pl 
#!/usr/bin/perl -n 

if (m!^2\d{3}/\d{2}/\d{2} !){
    print $prevline if $prevline =~ m/field13/;
    $prevline = $_;
}else{
    chomp($prevline);
    $prevline .= $_
}


root@virtualdeb:~# perl combine_and_filter < /tmp/in.txt
2012/12/31 field1 field2 field3 field4 field5 field6 field7 field8 field9 field10 field11 field12 field13
于 2013-02-08T20:45:50.183 回答
1

这可能对您有用:

awk --re-interval '/^[0-9]{4}\//&&s{print s;s=""}{s=s""sprintf($0)}END{print s}' file

用你的例子测试:

kent$  echo "2012/11/01 field1 field2 field3 field4 fi
eld5 field6 field7
2012/11/03 field1 field2 field3
2012/12/31 field1 field2 field3 field4 fi
eld5 field6 field7 field8 field9 field10 
field11 field12 field13
2013/01/10 field1 field2 field3
2013/01/11 field1 field2 field3 field4"|awk --re-interval '/^[0-9]{4}\//&&s{print s;s=""}{s=s""sprintf($0)}END{print s}'
2012/11/01 field1 field2 field3 field4 field5 field6 field7
2012/11/03 field1 field2 field3
2012/12/31 field1 field2 field3 field4 field5 field6 field7 field8 field9 field10 field11 field12 field13
2013/01/10 field1 field2 field3
2013/01/11 field1 field2 field3 field4
于 2013-02-08T20:48:41.230 回答
0

这是一个非常简短的脚本来完成这个。

sed '/^[[:digit:]]/ { :r N; /\n\([^[:digit:]]\)/ s:: \1:g; tr; } ' FILE

您对这种形式感到满意吗?

于 2013-02-08T20:58:54.383 回答