我有一个Perl模块,它将文本与数百个正则表达式的列表进行匹配;目前我只是在告诉他们:
if (
/?:re1/ or
...
/re200$/
) { return "blah"; }
有没有更好/更快/资源密集度更低的方法可以做到这一点?也许存在一个有用的模块,或者我应该将它们存储在散列中,等等。
我有一个Perl模块,它将文本与数百个正则表达式的列表进行匹配;目前我只是在告诉他们:
if (
/?:re1/ or
...
/re200$/
) { return "blah"; }
有没有更好/更快/资源密集度更低的方法可以做到这一点?也许存在一个有用的模块,或者我应该将它们存储在散列中,等等。
看看Regexp::组装
。
这来自描述:
Regexp::Assemble接受任意数量的正则表达式,并将它们组装为一个正则表达式(或RE),该正则表达式与所有单个RE匹配。
因此,目标字符串只需要针对一个表达式进行测试,而不需要有一个大的表达式列表来循环。当你有几千个模式需要处理时,这很有趣。我们付出了巨大的努力来制造尽可能小的图案。
还可以跟踪原始图案,这样您就可以确定在形成组合图案的源图案中,哪一个是导致匹配发生的图案。
我在一些项目中使用了它,它非常棒。
如何同时有效地匹配多个正则表达式?
(布赖恩·福伊供稿)
如果您有Perl 5.10或更高版本,这几乎是微不足道的。您只需针对正则表达式对象的数组进行智能匹配:
my @patterns = ( qr/Fr.d/, qr/B.rn.y/, qr/W.lm./ );
if( $string ~~ @patterns ) {
...
};
智能匹配在找到匹配时停止,因此不必尝试每个表达式。
早于Perl5.10,您还有一些工作要做。您希望避免每次想要匹配正则表达式时都编译它。在本例中,Perl必须为foreach循环的每次迭代重新编译正则表达式,因为它无法知道$pattern将是什么:
my @patterns = qw( foo bar baz );
LINE: while( <DATA> ) {
foreach $pattern ( @patterns ) {
if( /$pattern/i ) {
print;
next LINE;
}
}
}
qr//运算符出现在perl5.005中。它编译正则表达式,但不应用它。当您使用regex的预编译版本时,perl所做的工作较少。在这个例子中,我插入了一个映射,将每个模式转换为其预编译的形式。脚本的其余部分相同,但速度更快:
my @patterns = map { qr/$_/i } qw( foo bar baz );
LINE: while( <> ) {
foreach $pattern ( @patterns ) {
if( /$pattern/ )
{
print;
next LINE;
}
}
}
在某些情况下,您可以将多个模式组成一个正则表达式。不过,要小心需要回溯的情况。
my $regex = join | , qw( foo bar baz );
LINE: while( <> ) {
print if /(?:$regex)/i;
}
有关正则表达式效率的更多详细信息,请参阅Jeffrey Freidl的《掌握正则表达式》。他解释了正则表达式引擎是如何工作的,以及为什么有些模式效率低得惊人。一旦您了解了perl是如何应用正则表达式的,就可以针对具体情况对它们进行调优。
您可以将正则表达式保存在一个单独的文件中,每行一个。它不会运行得更快,但代码会干净得多。
用类似的东西把它们读进去
my @patterns;
while (<>) {
push @patterns, qr/$_/;
}
为了提高性能,我唯一的建议是使用真正的解析器ANTLR的perl目标似乎已经失效,但我使用通过perl的内联::Java在Java中生成的解析器时没有遇到任何问题。
编辑:确实考虑了另一件小事:将正则表达式从最常见匹配排列到最不常见匹配。可以给你一个小的持续因素改善。
如果您的regexp没有更改,那么您应该使用/o后缀,这将要求它们只编译一次。这将大大有助于提高速度。
此外,按照“最常见的拒绝优先”或“外卡最少的优先”对它们进行排序,这样之后的那些,更占用cpu的那些,执行频率最低。
当然可以从文件中读取它们,但为了提高速度,正确的方法是读取它们,然后在文本字符串中构造一个子例程,然后评估文本字符串以返回要调用的匿名子例程。这为您提供了硬编码regexp列表的速度优势以及regexp变量列表的灵活性。
I am building a Web interface to monitor an embedded system. I have built a Perl script which runs remote commands and gathers output from that system. Now what I need is a Web interface which makes ...
How do I tell what type of value is in a Perl variable? $x might be a scalar, a ref to an array or a ref to a hash (or maybe other things).
When I try a "chdir" with a filehandle as argument, "chdir" returns 0 and a pwd returns still the same directory. Should that be so? I tried this, because in the documentation to chdir I found: "...
I ve read the doc for GetOptions but I can t seem to find what I need... (maybe I am blind) What I want to do is to parse command line like this myperlscript.pl -mode [sth] [inputfile] I can use ...
I m a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot. package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I ...
I would like to submit a form to a CGI script localy (w3c-markup-validator), but it is too slow using curl and apache, I want to use this CGI script more than 5,000 times in an another script. and ...
So I m running perl 5.10 on a core 2 duo macbook pro compiled with threading support: usethreads=define, useithreads=define. I ve got a simple script to read 4 gzipped files containing aroud 750000 ...
A Google search yields a number of results - but which ones are the best? The Perl site appears to contain two - perlboot and perltoot. I m reading these now, but what else is out there? Note: I ve ...