如何在Perl中有效地匹配许多不同的正则表达式模式?

Joe*_*nte 5 regex perl

我有越来越多的正则表达式,我用它来解析搜索"有趣"错误和调试语句的日志文件.我现在将它们分成5个桶,其中大部分落入3个大桶中.到目前为止,我有超过140种模式,而且这个模式正在不断增长.

大多数正则表达式都很简单,但它们也相当独特,因此我用单一模式捕获多个匹配的机会很少.由于我匹配的性质,模式往往是模糊的,因此很少匹配,所以我在每个输入行上做一个TON工作,最终结果是它无法匹配任何东西或匹配最后的通用之一.

由于输入的数量(数百兆字节的日志文件),我有时会等待一两分钟才能完成脚本.因此,我希望有一个更有效的解决方案.不过,我对牺牲速度的清晰度并不感兴趣.

我目前的正则表达式设置如下:

 if (($line =~ m{Failed in routing out}) ||
  ($line =~ m{Agent .+ failed}) ||
  ($line =~ m{Record Not Exist in DB}) ||
         ...
Run Code Online (Sandbox Code Playgroud)

是否有更好的方法来构建它,以便它更有效,但仍然可维护?谢谢!

JB.*_*JB. 5

您可以将正则表达式与交替运算符组合|,如下所示: /pattern1|pattern2|pattern3/

显然,如果将所有这些都放在一行中,它将无法维护,但您可以选择减轻这种情况.

  • 您可以使用/x正则表达式修改器很好地隔开它们,每行一个.如果你选择这个方向,请注意:你必须明确指定你期望的空格字符,否则它们会被忽略/x.
  • 您可以通过组合各个源在运行时生成正则表达式.像这样(未经测试):

    my $regex = join '|', @sources;
    while (<>) {
        next unless /$regex/o;
        say;
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • / o已过时/已弃用.使用qr //.而且我认为在现代的perls中,只要$ regex不会改变,那么无论如何它都不会被重新编译.但不要引用我:-) (4认同)

dao*_*oad 5

您可能想看一下Regexp :: Assemble.它旨在处理这种问题.

从模块的概要中提升代码:

use Regexp::Assemble;

my $ra = Regexp::Assemble->new;
$ra->add( 'ab+c' );
$ra->add( 'ab+-' );
$ra->add( 'a\w\d+' );
$ra->add( 'a\d+' );
print $ra->re; # prints a(?:\w?\d+|b+[-c])
Run Code Online (Sandbox Code Playgroud)

您甚至可以从单独的文件中剔除正则表达式集合.

  • 绝对是要走的路.我有一个当前正在制作的应用程序,它使用Regexp :: Assemble将传入的文本字符串与1,334个术语的列表进行比较,以查看每个字符串中的哪些(如果有的话).代码很简单,运行良好,速度快. (2认同)