假设您有一份书面论文的文件。您想分析这篇文章,仅选择某些单词。凉。
使用正则表达式是否比逐行逐单词地查找匹配项更快?如果是这样,它如何运作?您如何比查看每个单词更快?
假设您有一份书面论文的文件。您想分析这篇文章,仅选择某些单词。凉。
使用正则表达式是否比逐行逐单词地查找匹配项更快?如果是这样,它如何运作?您如何比查看每个单词更快?
Answers:
它是如何工作的?
看看自动机理论
简而言之,每个正则表达式都有一个等效的有限自动机,可以将其编译和优化为有限自动机。涉及的算法可在许多编译器书籍中找到。这些算法由awk和grep之类的unix程序使用。
但是,大多数现代编程语言(Perl,Python,Ruby,Java(和基于JVM的语言),C#)都不使用这种方法。他们使用递归回溯方法,将正则表达式编译为树或代表正则表达式各个子块的结构序列。大多数现代的“正则表达式”语法提供的反向引用不在常规语言组中(它们在有限自动机中没有表示形式),可以在递归回溯方法中轻松实现。
优化通常确实会产生更有效的状态机。例如:考虑aaaab | aaaac | aaaad,普通程序员可以在十分钟内获得简单但效率较低的搜索实现(分别比较三个字符串);但意识到它等效于aaaa [bcd],可以通过搜索前四个'a'然后针对[b,c,d]测试第5个字符来进行更好的搜索。多年前,优化过程是我的编译器家庭工作之一,因此我认为大多数现代正则表达式引擎中也是如此。
另一方面,状态机在接受字符串时确实具有一些优势,因为与“简单的实现”相比,它们使用更多的空间。考虑一个程序来取消对SQL字符串的转义,即:1)以单引号开始和结束;2)用两个连续的单引号将单引号引起来。因此:输入['a''']应该产生输出[a']。对于状态机,连续的单引号由两个状态处理。这两个状态用于记住输入历史记录,以便每个输入字符仅被处理一次,如下所示:
...
S1->'->S2
S1->*->S1, output *, * can be any other character
S2->'->S1, output '
S2->*->END, end the current string
因此,我认为,在某些琐碎的情况下,正则表达式可能较慢,但由于人工无法可靠地进行优化,因此通常比手工制作的搜索算法要快。
(即使在诸如搜索字符串之类的琐碎情况下,智能引擎也可以识别状态图中的单个路径,并将该部分简化为简单的字符串比较,从而避免管理状态。)
框架/库中的特定引擎可能运行缓慢,因为该引擎执行了程序员通常不需要的其他许多操作。示例:.NET中的Regex类创建了一堆对象,包括Match,Groups和Captures。
aaaab|aaaac|aaaad
对aaaa[bcd]
。值得明确指出的是,两者在数学上是等效的,并且产生相同的DFA,因此使程序员有更大的自由来以有意义的方式表示正则表达式(不是这是通常的做法,而是...知道)。 ..
正则表达式看起来很快,因为您拥有快速的计算机。
早在1980年代1 MIPS是一台快速计算机时,正则表达式是一个相当大的担忧,关注和研究领域,因为它们速度慢,丑陋且计算量大。随之而来的是巧妙的算法开发并为之提供了帮助-但如今,出于所有实际目的,您已经看到了快速机器在裂缝上铺开的奇迹。
您为什么认为它们比搜索文档更快?
您可以采取一些技巧,例如。如果您要搜索一个以A开头并以B结尾的10个字母的单词,那么如果您找到A且后面第9个字符不是B,则可以跳过一些。请参阅Knuth–Morris–Pratt算法
您的基本前提是错误的。
正则表达式并不总是比简单搜索快。这完全取决于上下文。它取决于表达式的复杂性,要搜索的文档的长度以及许多因素。
发生的事情是正则表达式将被编译成一个简单的解析器(这需要时间)。因此,如果文档很小,那么额外的时间将超过任何好处。同样,如果表达式很简单,则正则表达式将不会给您带来任何好处。
如果表达式很复杂并且文档足够大,那么您可以获得一些好处。这是否足以使正则表达式考虑得更快,将在很大程度上取决于您要在搜索中付出多少努力(而且正则表达式可能会进行一些优化,而图书馆可能会提供一些优化,而您可能不会想到自己)。
我要说的是,没有广义的,笼统的答案。如果您有一个特定的表达式(和已知的文档大小),则可以说是/否答案,该表达式是否比简单的搜索更快(以及为什么)。
正则表达式的真正优势在于,一旦您了解如何编写它们,便能够以简洁的方式表达复杂的搜索。因为它是通用形式,所以您可以构建工具,以一种在一般情况下有用的方式进行搜索。它通常至少与简单搜索一样快(在最小尺寸的文档上;在小于此的文档上,这没有关系,因为即使速度较慢,它仍然足够快)。
在某些高级语言(可能是javascript)中,使用以低级语言(也许是C)实现的正则表达式库比用高级语言编写解析器逻辑要快。
可能-我不知道是否真的是这样。