字符类与“速记”类的表现

时间:2010-08-18 20:47:25

标签: regex

在回答另一个问题时,提出在显式字符类([0-9])和“速记”类(\d)之间可能存在性能差异。我最初的反应是,如果存在差异,它可以忽略不计,但我没有(并且找不到)任何关于它的信息或者弄清楚我如何测试它。

同样,[^0-9][^\d]\D之间会有不可忽视的差异吗?

2 个答案:

答案 0 :(得分:3)

当有疑问时,BENCHMARK!

我在Perl中对一个简单的正则表达式比较进行了基准测试。我发现\d+确实更快。 YMMV。

use strict; use warnings;
use Benchmark qw(:all);
use feature "switch";

my $r1='\d+';
my $r2='[0-9]+';
my $r3='[[:digit:]]+';

sub test {
    my @lines = <DATA>;
    $_=shift;
    my $RegEx=(caller(0))[3];
    given($_) {
        when(1) { $RegEx=$r1; }
        when(2) { $RegEx=$r2; }
        when(3) { $RegEx=$r3; }
        default { die "$RegEx can't deal with $_\n"; }
    }   
    my $ln;
    my $total;
    my @numbers;
    foreach my $line (@lines) {
        $total=0;
        @numbers=$line=~/($RegEx)/g;
        $total+=$_ for (@numbers) ;
        $ln=$numbers[$#numbers];
        $total-=$ln;
        if ($ln != $total) {
            print "Bad RegEx result: Last Num != total in line!\n";
            print "Total=$total, ln=$ln, line:$line";
            die;
        }       
    }   
}

cmpthese(-10, {$r1=>'test(1)', $r2=>'test(2)', $r3=>'test(3)'});


__DATA__
Clip clap clock 1 mouse ran up the clock with 3 hands. The total here is 4.
The mouse with 2 ears followed. The total here is 2.
After that, the 6 wiskered mouse did dances with 14 second timing. 20.
It is hard to make up 5 lines with 2 or 3 numbers in each line. 10.
You start thinking about nurserey rhymes with 1 o 2 or 3 number. 6.
1 12 13 123 23 13 55 66 21 45 1 373

我在OS X上使用Perl 5.10 64位得到以下结果:

                 Rate [[:digit:]]+       [0-9]+          \d+
[[:digit:]]+ 200781/s           --          -1%          -2%
[0-9]+       202831/s           1%           --          -1%
\d+          204605/s           2%           1%           --

以下是Ubuntu 10.04与Perl 5.10.1:

                 Rate [[:digit:]]+       [0-9]+          \d+
[[:digit:]]+ 264412/s           --          -3%          -6%
[0-9]+       273202/s           3%           --          -3%
\d+          280541/s           6%           3%           --

答案 1 :(得分:1)

好吧,不知道实现(并且不想在Reflector中使用数百行代码),很难确定,所以让我们尝试一些疯狂的推测。

  • 假设A)“[J-P]”的编码类似于"JKLMNOP".Contains(chr)
  • 假设B)通过Char.IsDigit(chr)
  • 可以更快地完成对数字的搜索

鉴于此,归结为两个问题:

  • Regex可能会将\d视为特例并使用IsDigit吗? - 我认为这很可能。
  • Regex是否可能将[0-9]识别为与[J-P]不同的特殊情况并使用IsDigit代替Contains? - 我认为这是可能的,但不太可能。

所以,我说有可能\ d比[0-9]更快。

(注意:我使用C#/ .NET作为示例,但无论平台如何,基本原则应该相同)