2011-05-21 32 views
5

我已经看到了这个以前的帖子,关于对多个正则表达式 How can I match against multiple regexes in Perl?如何在Perl中匹配多个正则表达式?

我在找最快的方式,以匹配包含在数组中对一个非常大的文件(500 MB)的所有值匹配。

这些模式是从stdin中读取的,并且可能包含必须在正则表达式(锚,字符类等)中使用的特殊字符。当全部模式包含在当前行中时,必须发生匹配。

目前我使用一个嵌套循环,但我不是很满意,速度....

感谢您的建议。

+3

您是如何确认500MB数据的IO速度不是限制因素的? – Richard 2011-05-21 17:39:14

+1

作为一个简单的优化,确保最有可能失败的正则表达式被测试_first_。这样,当发现故障时,您可以尽快跳到下一个记录。 – pjf 2011-05-21 17:43:08

+2

也许你应该向我们展示一些代码和正则表达式,所以我们可能有一些工作。此外,有关输入可能看起来如何的任何信息。 – TLP 2011-05-21 18:02:14

回答

4

你试过用grep吗?

while($line=<>) { 
    if (scalar(grep($line=~/$_/,@regexps))==scalar(@regexps)) { 
     # ... All matched 
    } 
} 
+1

或简单地'if(!grep {!condition} @list){...}' – Dallaylaen 2011-05-21 19:41:23

+0

谢谢代码很简单,似乎工作 使用5.014; my @ regexps = qw(foo?bar {2} [Rr] at^this barren $); my $ line ='这种食物比较贫瘠'; (标量(grep($ line =〜/ $ _ /,@ regexps))==标量(@regexps)){ 说'全部匹配'; }
else {say'not all matched'} – user764169 2011-05-23 10:26:08

8

尝试Regexp::Assemble为您链接到后建议和比较,像grep迭代方法。 Regexp :: Assemble应该生成最快的解决方案,因为Perl可以优化加入的正则表达式,而不是为每一行扫描整行。既然你事先不知道你的输入,ymmv。

您正在使用哪种版本的Perl会影响性能。 5.10为此目的引入了很多优化(请参阅“tries”)。最大的用例之一就是SpamAssassin等垃圾邮件扫描程序,它们像Regexp :: Assemble一样构建了所有扫描模式的大正则表达式。

最后,由于您的输入过大,因此将正则表达式汇编到文件中然后运行grep -P -f $regex_file $big_file可能是值得的。 -P告知grep使用Perl兼容的正则表达式。该文件用于避免shell引用或命令大小限制。 grep可能会关闭Perl。最后,你将不得不做基准测试。

+1

Regexp :: Assemble的问题是,当它匹配一个条件时,返回“成功”,我需要在所有条件上匹配。我认为继续使用嵌套的“for”循环会更快。 我使用perl 5.14(通过梦幻般的perlbrew)。 – user764169 2011-05-23 10:13:20