我有一些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
答案 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,
}
);