我正在解析一个日志文件,试图拉出短语“failures =”是一个唯一的非零数字的行。
我的perl one liner的第一部分将拉出“失败”大于零的所有行。但是日志文件的那一部分会重复,直到发生新的故障,即在第一次失败之后,日志条目将是“失败= 1”,直到第二次错误然后它将读取,“失败= 2”。
我想做的只是拉出那个值发生变化的第一行,我以为我有这个:
cat -n Logstats.out | perl -nle 'print "Line No. $1: failures=$2; eventDelta=$3; tracking_id=$4" if /\s(\d+)\t.*failures=(\d+).*eventDelta=(.\d+).*tracking_id="(\d+)"/ && $2 > 0' | perl -ne 'print unless $a{/failures=\d+/}++'
然而,这只会拉出第一个非零“失败”线而没有别的。我需要更改什么来为“失败”提取所有唯一值?
提前感谢!
更新:每行中直到“tracking_id”的文字数量都比我发布的文字多。遗憾!
2011-09-06 14:14:18 [INFO] [logStats]:name = somename id = d6e6f4f0-4c0d-93b6-7a71-8e3100000030 成功= 1次失败= 0跳过= 0 eventDelta = 41 original = 188模拟= 229 totalDelta = 41 averageDelta = 41 min = 0 max = 41 averageOriginalDuration = 188 averageSimulatedDuriation = 229(txid = b3036eca-6288-48ef-166f-5ae200000646 date = 2011-09-02 08:00:00 type = XML xml =
答案 0 :(得分:2)
perl -ne 'print unless $a{/failures=\d+/}++'
不起作用,因为在标量上下文中计算哈希下标,并且m//
运算符不会在标量上下文中返回匹配。相反,它返回1.所以(因为每一行匹配),你写的相当于:
perl -ne 'print unless $a{1}++'
我认为你可以在那里看到问题。
有很多方法可以解决这个问题,但我会使用:
perl -ne 'print unless /(failures=\d+)/ and $a{$1}++'
但是,我会在perl
的一次调用中完成所有操作,包括对行进行编号:
perl -nle '
print "Line No. $.: failures=$1; eventDelta=$2; tracking_id=$3"
if /failures=(\d+).*?eventDelta=(.\d+).*?tracking_id="(\d+)"/
&& $1 > 0
&& !$seen{$1}++
' Logstats.out
($.
自动计算Perl中的输入行。如果需要,可以删除换行符,但它实际上会按原样运行。)
答案 1 :(得分:1)
你可以使用哈希来存储结果并打印出来:
perl -nle '$f{$2} ||= "Line No. $1: failures=$2; eventDelta=$3; tracking_id=$4" if /\s(\d+)\t.*failures=(\d+).*eventDelta=(.\d+ ).*tracking_id="(\d+)"/ && $2;END{ print $f{$_} for keys %f }' Logstats.out
(由于缺少输入数据而未进行测试......)
HTH, 保罗
答案 2 :(得分:1)
由于您的输入与正则表达式不匹配,我无法真正帮助您。但是我可以告诉你,这是一个很多的回溯 - 如果在你感兴趣的部分之后有很多数据,那就太糟糕了。
所以这里有一些替代的想法:
qr{ \s # a single space
failures=(\d+) # the entry for failures
\s+ # at least one space
skipped=\d+ # skipped
\s+
eventDelta=(.\d+)
.*? # any number of non-newline characters *UNTIL* ...
\btracking_id="(\d+)" # another specified sequence of data
}x;
解析器将扫描“skipped =”,然后扫描一组数字比扫描其余部分要快很多,并且当它返回'eventDelta ='时回溯,最好将其放入,如果你知道它将永远存在。
由于你没有在你的例子中放置tracking_id
,我不知道它是如何发生的,所以在这种情况下我们使用非贪心任何匹配将永远寻找下一个序列。同样,如果该行中有大量数据,那么您不想扫描然后结束并回溯,直到您发现您已经读过'tracking_id =“nnn”'。但是,前瞻会花费处理时间,最好拼出'skipped ='和所有可能的值,然后是非贪婪的“任何匹配”。
您还会注意到,在接受任何数据后,我指定tracking_id应出现在单词边界,这可以消除可能的歧义 - 虽然不太可能'backtracking_id ='。