哪个更有效的正则表达式?

时间:2009-02-13 10:52:30

标签: regex performance perl

我正在解析一些日志文件,并且有一些非常简单的字符串匹配,例如

if(m/Some String Pattern/o){
    #Do something
}

看起来很简单,但事实上我所拥有的大多数比赛都可以对抗线的开头,但比赛将会“更长”,例如

if(m/^Initial static string that matches Some String Pattern/o){
    #Do something
}

显然,这是一个更长的正则表达式,因此需要更多工作来匹配。但是我可以使用行锚的开头,这将允许表达式更快地作为失败的匹配被丢弃。

我的预感是后者会更有效率。任何人都可以支持我/击落我: - )

7 个答案:

答案 0 :(得分:6)

我认为你会发现用^开始正则表达式肯定会更快,因为正则表达式引擎不需要查看字符串左边缘的任何进一步匹配。

当然,这是您可以轻松测试和测量的内容。做正则表达式匹配1000万次左右,测量需要多长时间,然后再使用不同的正则表达式再次尝试。

答案 1 :(得分:4)

线锚使其更快。我必须补充说,这里不需要// o修饰符,事实上它什么都不做。那是我的代码味道。

曾经有过有用的用法,但是这些日子是由qr //

提供的

答案 2 :(得分:3)

RE的速度取决于两个因素,即RE本身和通过RE的数据。通常,没有回溯的锚定RE(开始或结束)将比其他更快。但是,如果您正在处理每行都为空的文件,则/^hello//hello/之间没有速度差异(至少如果RE引擎写得正确的话)。

但我遵循的规则是:衡量,不要猜测。

答案 3 :(得分:3)

我按照建议做了一些时间安排。这是我的应用程序的结果。它是整个应用程序,而不仅仅是正则表达式搜索。它扫描了60,000行。 11正则表达式平均短长度约为30个字符。较长但锚定的约为120。

Short
   real    0m58.780s
   user    0m54.940s
   sys     0m0.790s

Long (anchored)
   real    0m54.260s
   user    0m53.630s
   sys     0m0.490s

Long (not anchored)
   real    0m54.705s
   user    0m54.130s
   sys     0m0.400s

因此锚定长字符串会稍快一些。虽然不是很多。看来,如果我的字符串更大,那可能是另一回事。

答案 4 :(得分:2)

使用use re debug编译指示,您可以深入了解正则表达式引擎在Perl中的作用。记录在案here

查看Perl suggested performance techniques总是有帮助的,包括建议的计时方法。

如果我进行这个小测试:

#!/usr/bin/perl 

use strict;
use warnings;
use Benchmark;

my $target="aeiou";

my $str="lkdjflzdjfljdsflkjasdjf asldkfj lasdjf dslfj sldfj asld alskdfj lasd f";

my $str2=$str.$target;

timethese(10_000_000, {
            'float'       => sub {
                die "no match" unless $str2=~m/$target/o;
            },
            'anchored'  => sub {
                die "no match" unless $str2=~m/^.*$target/o;
            },
            'prefixed'   => sub {
                die "no match" unless $str2=~m/^$str$target/o ;
            },  

    });

我得到了输出:

Benchmark: timing 10000000 iterations of anchored, float, prefixed...
  anchored:  4 wallclock secs ( 3.46 usr +  0.01 sys =  3.47 CPU) @ 2881844.38/s 
     float:  2 wallclock secs ( 1.87 usr +  0.00 sys =  1.87 CPU) @ 5347593.58/s 
  prefixed:  4 wallclock secs ( 3.05 usr +  0.01 sys =  3.06 CPU) @ 3267973.86/s 

这导致了非锚定(浮动)版本更快的结论。但是,正则表达式和源代码可能会改变这种情况。 YMMV和测试测试...

答案 5 :(得分:1)

你是说你可以通过添加一个静态前缀来锚定正则表达式吗?

/^blah blah The Real Regex/

这肯定不会伤害性能,它可能会有所帮助,但不是因为你认为的原因。虽然他们最着名的是“神奇”的东西,比如锚点和外观以及捕获组,但正则表达式引擎最擅长的是匹配字符序列。序列越长,匹配越快(当然直到某一点)。

换句话说,它是添加静态前缀而不是锚点,它可以为你提供支持。

答案 6 :(得分:0)

我投票支持开头的那个,正是因为你陈述的原因!