【问题标题】:How to keep the last consecutive line that matches with Perl如何保留与 Perl 匹配的最后一个连续行
【发布时间】:2018-10-02 15:58:27
【问题描述】:

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

例如,如果我有很多带有字符“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 中的错误,还是在某处记录?最好的方法是什么?

我正在使用 perl 5.22.1。

【问题讨论】:

    标签: regex perl text


    【解决方案1】:

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

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

    根据perldiag

    超过复杂正则子表达式递归限制 (%d) (W regexp)

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

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

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

    【讨论】:

    • 为答案添加了解决方案。
    猜你喜欢
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    相关资源
    最近更新 更多