如何保持与Perl匹配的最后连续行

时间:2018-10-02 15:58:28

标签: regex perl text

我正在尝试匹配文本文件中的连续相似行,并且仅保留最后一行。每行包含一个数字计数,所以我要匹配文本和数字以获取计数。

例如,如果我有很多连续的字符为'a'的行,则可以按以下方式进行操作。

$ (for i in `seq 1 1 100000`; do echo a; done;) | 
    perl -0777 -pe 's/(a\n)*(a\n)/\2/igs'
a

但是,如果我将它与数字的其他匹配项一起使用,则perl似乎会以2 ^ 15的批次进行处理。

$ (for i in `seq 1 1 100000`; do echo $i; done;) | 
    perl -0777 -pe 's/(\d*\n)*(\d*\n)/\2/igs'
32768
65536
98304
100000

我做错什么了吗,这是perl中的bug,还是记录在某处?最好的方法是什么?

我正在使用perl 5.22.1。

1 个答案:

答案 0 :(得分:1)

如果将警告编译指示添加到perl脚本中,则会获得以下信息:

Complex regular subexpression recursion limit (32766) exceeded at -e line 1, <> chunk 1.

根据perldiag

  

超出了常规规则子表达式递归限制(%d)(W regexp)

     

在复杂情况下,正则表达式引擎使用递归   需要回溯的地方。递归深度限制为32766,   或在堆栈无法增长的架构中更少   任意地。 (“简单”和“中等”情况在没有   递归并且不受限制。)尝试缩短字符串   正在检查中;在Perl代码中循环(例如with while)而不是   在正则表达式引擎中;或重写正则表达式   以便更简单或减少回溯。 (有关详情,请参见perlfaq2   有关掌握正则表达式的信息。)

以下是您可以使用的解决方案:

perl -ne'
   if (/^\d+\n) { $buf = $_; next; }
   print(substr($buf, 0, -1, ""), $_);
   END { print($buf) }
'