Perl,预编译regexps组的匹配数组

时间:2014-02-15 18:33:54

标签: regex perl

我有一些regexp组,想要匹配每一个的当前行,如果匹配成功则调用一些匹配组作为参数的函数。

my %regexps = (
    "a" => qr/^(a)\s*(b)/o,
    "b" => qr/^(c)\s*(d)/o,
    "c" => qr/^(e)\s*(f)/o,
);

sub call_on_match {
    my $actions = shift;
    # ... some setup actions for $_
    while (my ($regexp, $func) = each(%$actions) ) {
        if (my @matches = /$regexp/){
            $func->(@matches);
        }
    }
}

call_on_match({ 
    $regexps{"a"} => \&some_funca,
    $regexps{"b"} => \&some_funcb,
    $regexps{"c"} => \&some_funcc,
})

问题出在my @matches = /$regexp/表达式中,它执行大约110k次并且总共花费大约1秒进行编译(此行的典型分析器输出:# spent 901ms making 107954 calls to main::CORE:regcomp, avg 8µs/call。 首先猜测是删除额外的正则表达式斜杠,以防它使perl认为它是新的正则表达式并且必须编译。我使用了my @matches = ($_ =~ $regexp),但没有成功。 还有另一种方法可以让perl不在这种情况下重新编译qr'ed regexp吗?

UPD:我用数组​​替换哈希(如[$regexps{"a"}, \&some_funca]):

foreach my $group (@$actions){
    my ($regexp, $func) = @$group;
    if (my @matches = ($_ =~ $regexp)){
           $func->(@matches);
    }
}

现在编译速度更快但编译不会消失:# spent 51.7ms making 107954 calls to main::CORE:regcomp, avg 479ns/call

1 个答案:

答案 0 :(得分:1)

我建议您使用ID作为两个哈希中的键,就像这样

use strict;
use warnings;

my %regexps = (
  a => qr/^(a)\s*(b)/,
  b => qr/^(c)\s*(d)/,
  c => qr/^(e)\s*(f)/,
);

sub call_on_match {

  my ($actions) = @_;

  # ... some setup actions for $_

  while (my ($regexp_id, $func) = each %$actions) {
    if (my @matches = $_ =~ $regexps{$regexp_id}) {
      $func->(@matches);
    }
  }
}

call_on_match(
  {
    a => \&some_funca,
    b => \&some_funcb,
    c => \&some_funcc,
  }
);