为什么我只得到一场比赛?

时间:2011-09-08 15:30:33

标签: perl

我正在解析一个日志文件,试图拉出短​​语“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    =     

3 个答案:

答案 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 ='。