就像之前的MySQL详细全面优化写作,因为这些工具的广泛使用,这种工具的优化策略,全是很划算的,因为无论你是PHP、Perl、Python、C++、C #,java语言的程序员,你可以使用MySQL的正则表达式很有可能是这样的工具。

首先,您可能不知道的正则表达式的一些知识,这对我们未来的优化是有用的。
最常见的grep(全局正则表达式打印)是正式制度的起源现在。(从神经科学家提出了正则化的数学家,概念没有大规模使用IBM建立模型,直到最后成为grep独立工具的使用更多)。现在,我们使用正则化分为POSIX的两所学校(便携式操作系统接口):BREs(基础正则表达式)和EREs(扩展表达式)。POSIX程序必须支持一个。两个具有不同的特点,需要被理解。详情看前一篇文章中的shell脚本学习指南{ 1 }三,常见的3中的正则表达式比较部分。

正则匹配引擎可以分为两大类:DFA和NFA。前者是确定性有限自动机,后者是一个非确定性有限自动机。编译原理是说有另一个维基的兴趣。现在的规则引擎分为三类:

1、DFA引擎中执行的线性时间的状态,因为它们不需要回溯(因此他们不会测试相同的字符的两倍)。DFA引擎也能保证尽可能长的字符串匹配。但是,因为DFA引擎只包含有限的状态,它不能与落后的参考模式比赛中,因为它不构成显示扩展,它不能捕获子表达式。
2、传统的NFA引擎运行所谓的贪婪匹配回溯算法,测试正则表达式的所有可能的扩展在一个指定的顺序和接受的第一场比赛。因为传统的NFA构造正则表达式的特定实现成功匹配的扩展,它可以捕获和子表达式匹配的反向引用。然而,由于传统的NFA回溯,它可以访问相同的状态,很多次(如果达到,通过不同的路径状态)。因此,在最坏的情况下,它的执行可能会很慢,因为传统的NFA接受它找到的第一个匹配,它也可能导致其他(可能更长时间)的比赛不被发现。
3、POSIX NFA引擎是类似于传统的NFA引擎。不同的是,他们将继续回溯才可以确保最长的比赛被发现。因此,POSIX NFA引擎的速度比传统的NFA引擎慢,当你使用POSIX NFA,你不会愿意支持短匹配搜索的同时改变回溯搜索序列,而不是长匹配搜索。

根据常规发动机的不同,我们可以归纳出两条通用规则:
1,选择最左边的匹配结果。
2。标准匹配量词(**){ },m })是第一个匹配。

下面是几个简单的优化示例:
例如,{ } {。* 0-9 0-9 }匹配的字符串abcd12efghijklmnopqrstuvw,然后是第一。* 'matching整行,但不能在比赛后满足两个数,所以*返回一个字符W,仍然无法比拟的,继续返回一个V的2回归的环流特征,找到匹配的一个,但仍无法匹配两个数,所以继续返回1。当我们了解了这个特点,我们应该尽量避免它。如果我们想要一个包含两个数字,两个数是直接的,好了,不写。*这个通配符。在学习优化学习优化的底层实现是实现,因为一路上的工具来达到自己想要的效果,如果你不理解下说谎工具,你不太清楚什么情况适合用什么工具。

从上面的DFA和NFA的介绍,我们知道它们之间的区别。总之,NFA和DFA的表达主要的发动机,是文字为主的发动机。一般来说,DFA级发动机只匹配目标字符串中的每个字符一次,但NFA将回溯。文本LED DFA将比NFA以表达更快。

可以注意到如何避免NFA回溯尽可能将为正规NFA引擎的优化是一个大问题。有一个是否忽略优先匹配的问题,还有一点需要优化,优先匹配一个简单的解释是,因为在上侧的普适规则也提到,当匹配到的位置并试图匹配或不匹配,当分类器匹配,发动机将优先尝试的行为,而忽略了分类器的优先级,跳过尝试匹配。例如,如何做好这两点工作,为什么他们需要优化:

用abc来匹配abc,程序流程是这样的:
匹配第一个没有问题。当你匹配B时,引擎将是因为要考虑是否匹配B,默认是量词优先,所以第一个匹配完成,另一个处于替代状态。这与ab匹配,然后成功匹配C,因此程序结束,替代状态放弃。

如果ABC仍然被用来匹配ac,当程序运行到B时,它将首先匹配B并发现它不是。在这个时候,它会回去,就是回到比赛的状态,那么程序将继续运行,并匹配C,然后将它完成。过程的追溯,以及学习算法的过程是很好的理解。它是第一个出栈,这是一个更方便的回溯过去的法律状态。

让我们来看看忽略优先级匹配,例如匹配AC与ABC,匹配第一,然后B。在这个时候,我们将放弃分类器,跳过B的匹配,以匹配C第一,这样的匹配成功结束,没有事先回溯过程。

再看看不成功的比赛,让ABX匹配ABC。你会发现,这个程序匹配A,然后尝试B,B变为,然后尝试C,C不返回到不匹配B的状态,试图匹配x,仍然不能匹配。然后返回,然后移动起始位置,尝试从B,而不是尝试从C开始在结束时得到不匹配的报告。

总的来说,这两点,你经常写需要小心避免回溯和确定你的固定场所需要避免优先级匹配。上面的例子很简单,但如果你避免回溯,可以减少从平方级程序的时间复杂度O(n)对线性O(n),当然,这是理想状态。

*和+回溯类似上述过程,如××,这可以被视为XXXX…所以或(x(x)(x)))所以,想象在很多层迭代,突然一个X不匹配,这就需要一层一层的回溯如果有一个匹配。* { 0-9 },这样的表情,第一次比赛的第一场比赛,这使得它可以完成整个字符串匹配,然后一步一步回来,返回的字符,无论是数字,可以直接匹配到一个数字,所以上述。这样的通配符,如果不是必须的话,就不要写这样的通配符。

此外,DFA不支持忽略优先级,只支持匹配优先级,这一特性非常贪婪。而且容易忽略,不正确的使用会得到我们可能不需要的结果。*)括号,目标字符串是ABCD(AAAA)EFG(GGG)H.根据性质,将匹配的第一个(从开始一直匹配的线,最后再根据角色的需要)返回一个字符相匹配)。问题出现了,在最后一场比赛(AAAA)EFG(GGG),这不是我们想要的结果。事实上我们需要的正则表达式(是^(){ } *)。这个错误是特别小心在HTML标签,如123456789,如果你想匹配和替换,你会错。但你想用一个类似的({ ^()}×)。这样,请考虑一下这个问题,这样你就更错误了。例如,123 ,用的是{ },显然,完全不能匹配。你想办法吗只需要放弃,优先这一原则的一个很好实现,如,*,*会优先将首先尝试匹配,如果不吸收。也许你已经发现,这仍然是一个问题,因为123456,匹配结果仍然不是我们所喜欢的,因为比赛回到123456,我们希望得到456。一个更好的解决办法是在函数中使用的标准看,这需要在一个单独的眉目传情的理解。

在顶部,我们介绍了两种优先尝试模式和跳过尝试。正确使用有助于规则的优化。另一种模式是巩固分组(>表达)。特别是,有治疗组和正常的比赛没有区别,但如果表达式匹配成功,它将巩固的结果而放弃任何其他国家。看一个例子: W +:让他尝试匹配的HelloWorld,我们可以看到,这是不匹配的,因为它不包含冒号,为了比较固化,我们还描述这个过程:第一, W将匹配字符串的末尾,然后尝试匹配:D号不匹配。所以 / W返回下一个字符,匹配,R不工作,一个小时或不匹配和报告的结果相匹配。如果你使用固化分组模式(> W +):HelloWorld匹配过程:首先,到终点,然后发现不匹配的结肠,报告匹配不成功。因为我们知道 W是无法匹配的符号,所以如果 W可以匹配的内容,它不会是一个冒号,所以没有必要保持选择状态 W的产生,使匹配过程可追溯到。固化包可以很好地消除这些选择的状态。如果你想尝试,请确保你的工具支持常规的固化组。

量词的优先级是:*,+,+,+,m,n + +。这种模式匹配,量词优先匹配和优先级匹配与量词是不同的。在这种模式下,量词匹配的部分不会返回,即去掉量词匹配过程中产生的交替模式。

多结构的匹配是一个类似| B | C,和传统的NFA的执行序列匹配,各分行将耗尽所有可供选择的状态,这种有序的匹配的特点是能够发现一点优化方法,使匹配成功的可能性尽可能。

上面有很多东西,其中大部分都涉及到NFA,许多正规的优化是在预编译阶段的NFA NFA做engine.dfa和正则表达式到合适的算法,但DFA需要更多的内存,和比NFA慢,但正式实施的过程,DFA的速度比NFA,即使你写的正则表达式是不好的,但也为NFA没有结束,一个尴尬的局面。但是为什么NFA仍然存在仍然是主流,或者可以提供的功能,DFA不能提供。例如,上面提到的所有匹配的模式不由的DFA。

NFA和DFA不能共存,和一些工具有两个匹配引擎做出自己的DFA高效和NFA多才多艺。例如,grep和awk GNU使用高效的DFA引擎在完成匹配任务。当完成复杂的任务时,他们也尝试使用DFA。如果功能不能满足需要,他们会切换到NFA引擎。

以上是一个相对混乱的例子的一些知识和DFA和NFA的规则引擎规则优化。我们也知道不会有太多的优化策略对正则表达式的DFA引擎,有些是准确的,你可以尝试一些匹配正则表达式,NFA引擎的正则表达式,我们有更大的优化空间,但这之前,你需要区分你使用的工具是基于传统的NFA或POSIX NFA。有些问题可能只有一个引擎的存在,会对其他影响不大。

为了避免回溯,我们应该避免指数增长的回溯。例如,表达式({ ^ / } +)*:每次一个字符必须被考虑,应该属于属于* +量词量词,所以,如果一个长度为10的字符串,然后回1023次,第一次不回来,这是2的指数增长,如果字符串增加到20个,一百万以上的可能,往往几秒,如果是30,超过十亿的可能,你必须运行几个小时,如果超过40个字符,它要求你等待超过一年。这实际上给了我们一种规则引擎识别工具,您使用:
1,如果某个表达式不能匹配,它也可以给出结果,那么它可能是DFA,只是可能的。
2。如果它能给的结果很快,这是传统的NFA。
3,总是很慢,这是POSIX NFA。

第一是可能的,因为先进的优化NFA能够给结果快。

有很高的成本替代回溯结构,如| B C D E | | | | F和{ A-F },{ A-F字符数组}只需要做一个简单的测试,但在匹配位置的每一次选择的结构将超过6替代状态回溯。

现在很多常规编译器会做很多你不知道的优化,但是如果你注意到的话,常识优化总是好的,因为你使用的工具是优化的。

1。如果支持常规工具,则在不需要引用括号中的文本时使用非捕获括号:((表达式))。
2。如果没有括号,请不要添加括号。
三.不要滥用字符数组,如{ },请直接使用。
4。使用锚点,这将加快定位速度。
5。从两次,如提取要素:X +写成XX *,和{二}是{ 0 }写为AA。
6开始时的同一个字符。提取的多选结构,如|为TH(:E |是)。如果你的正则引擎不支持使用,它将改变TH(E |是)。特别是锚固点必须是独立的,所以很多老的编译器会根据定位点做出特别的优化:^ 123 | ^ ABC改为^(123 | ABC)。相同的美元也尽可能独立。
7后面的表情。选择结构成多个结构,这可以匹配,当任何一个结构中的多个结构在不多出口视图的情况下,更快地匹配失败,这个优化需要谨慎使用。
8。忽略优先级匹配和优先级匹配需要您确定情况。如果您不确定,使用匹配优先级,这比忽略优先级要快。
9。把较大的正则表达式分解成小的正则表达式,这对提高效率很有帮助。
10、模拟锚点,用适当的环结构预测合适的起始匹配位置。如果我们的比赛十二个月,我们可以先检查第一个字符匹配:(= jfmasond)(:1月| |…| DEC),使用优化,根据实际情况,有时视觉结构的开销可能会更大。
11。在许多情况下,使用固化组和占有优先级量词可以大大提高速度。
12。避免无休止的比赛几乎一样(这|,)*。上述(…+)*是相似的。
13。如果对目标字符串进行简单匹配,可以进行许多常规匹配,在实践中非常有效。
PS:这可能比较混乱,主要是指精通正则表达式(第三版)}(美国)jeffrey.e.f.friedl这本书,另两人的博客可以看到,通过信基本覆盖。