Regex perl中的正则表达式是否比Java或其他语言更快?

Regex perl中的正则表达式是否比Java或其他语言更快?,regex,performance,perl,Regex,Performance,Perl,我经常听到人们说Perl中的正则表达式比其他语言更快。此外,一些在线文档还说Perl在正则表达式处理方面有优势。你们能解释一下这是不是真的,为什么吗?关键不在于Perl比Java快(基准测试会告诉你们),而在于regexes是语言本身的一部分。举个例子,在Perl中,使用正则表达式不需要加载任何模块。看 例如,伪终端中的Perl一行程序(打印根的外壳): 在Java中做同样的事情需要多少行 Perl实际上是正则表达式的参考语言。这就是为什么这么多语言使用引擎(这意味着与Perl兼容的正则表达式)

我经常听到人们说Perl中的正则表达式比其他语言更快。此外,一些在线文档还说Perl在正则表达式处理方面有优势。你们能解释一下这是不是真的,为什么吗?

关键不在于Perl比Java快(基准测试会告诉你们),而在于regexes是语言本身的一部分。举个例子,在Perl中,使用正则表达式不需要加载任何模块。看

例如,伪终端中的Perl一行程序(打印根的外壳):

在Java中做同样的事情需要多少行

Perl实际上是正则表达式的参考语言。这就是为什么这么多语言使用引擎(这意味着与Perl兼容的正则表达式)

您可以看看。在表中,
patmch:1t
列给出了匹配URL与
/([a-zA-Z][a-zA-Z0-9]*):/([^/])+(/?[^]*)/
,而
patmch:2t
列给出了匹配URL或电子邮件与
/([a-zA-Z][a-zA-Z0-9]*):/(//(^]+)(/?[^])+)(/?[^]*)/)(^+)/)([^+)/)([^+)/)/([^+)/)([^+)/)/(请注意
)。对于第一种模式,Perl大约比Java快10倍;第二,它们大致相同

通常,Perl使用回溯正则表达式引擎。这种引擎灵活、易于实现,并且在正则表达式的子集上运行速度非常快。但是,对于其他类型的正则表达式,例如当存在
|
操作符时,它可能会变得非常慢。在极端情况下,其匹配速度与模式长度成指数关系。另一种类型的正则表达式引擎基于NFA。它更难实现,但对于所有类型的输入都有稳定的性能(最差IIRC为二次型)。关于这些话题,我非常喜欢

我不知道Java正在使用什么类型的正则表达式引擎,但从基准测试来看,它的性能似乎并不令人印象深刻。您可能还对在正则表达式上计算几个C/C++库的方法感兴趣

编辑:在这两个基准测试中,模式都是针对旧版本的Linux Howto进行测试的。绝大多数行没有匹配项

关于DFA和NFA:如果我是对的,一个纯DFA不能捕获组,至少不容易。只有NFA才能捕获组。我听说,对于没有组捕获的regex部分,将本地NFA转换为DFA。我不知道这是不是真的


在PCRE上:PCRE与Perl有同样的问题——在复杂的交替中效率低下。您可以从计算机语言基准测试游戏中查看。使用PCRE的版本都比使用TCL的最快版本慢得多(可能PCRE没有使用trie?)。V8显然是该基准测试的赢家,因为。IMO,对于C++程序员来说,最好的正则表达式库是R2.2./P>< P>当两个引擎(java)中有一个明显的错误时,为什么你会考虑两个引擎的速度?(搜索Tom“tchrist”Christiansen关于该主题的文章。)例如,
\s
无法匹配许多空格字符

此外,一些在线文档还说Perl在正则表达式处理方面有优势

以下是一些:

  • 具有许多在其他引擎中找不到的功能,可能是因为其他引擎尚未复制这些功能,或者是因为它们的设计不允许它们支持这些功能
  • 高度优化。许多这样的优化有助于更快地报告失败的匹配,这是许多基准测试所没有涵盖的
  • Unicode支持方面的领先者。它的支持非常先进,以至于我们的开发人员发现了Unicode标准本身的问题,并努力解决这些问题
  • 完全没有bug

不确定Perl与Java的对比,但Perl的速度比普通的grep快得多。有一次,我将一个大文件的20分钟grep作业转换为一个15秒的perl正则表达式。@Magnus:您使用的语言环境正确吗?对我来说,grep总是比perl快得多,因为grep不需要执行诸如捕获组之类的附加操作。几年前,当您在语言环境中指定UTF8时,随Linux发行版(grep、sed等)提供的gnutools中的文本处理程序的运行速度慢了大约100倍。(例如,请参阅)Perl的正则表达式引擎经过专门优化,可以快速查找失败的匹配。您链接到的基准测试是否测试了这一点???Perl使用尝试进行替换,而不是NFA。您的信息似乎已经过时十年了。@ikegami-我分析答案的方式是,NFA被提到是一种替代方法,而不是被Perl使用。@user172818是的,trie优化用于所有替代方法都知道起始字符串的替代方法。另外,如果您想要在Perl中使用Russ的正则表达式匹配器,那么只需
使用re::engine::RE2
;(“a“x$n)=~/(a?{$n}a{$n}/;”30
。这需要永远<代码>?
是运算符,而不是符号。它极大地增加了回溯的可能性。其他类型的集成您在别处找不到:
'abc'=~/(.*)({push@matches,$1})(*FAIL)/
@ikegami-我很想问这个问题,一个好的解释会丰富这一点。@sputnick-集成比不需要加载模块要深入得多(对于编译语言来说,这并不是什么大问题)。正是因为有了使用
/e
修改器的能力,以及对命名捕获的支持,使得集成变得如此独特。@ikegami:我认识到这一点。。。
perl -nE '/^root.*:([\/\w]+)$/ and say $1' /etc/passwd