展开循环,何时使用

2 javascript regex

我试图了解正则表达式中的展开循环。之间的最大区别是:

MINISTÉRIO[\s\S]*?PÁG
Run Code Online (Sandbox Code Playgroud)

MINISTÉRIO(?:[^P]*(?:P(?!ÁG\s:\s\d+\/\d+)[^P]*)(?:[\s\S]*?))PÁG
Run Code Online (Sandbox Code Playgroud)

在这种情况下:

http://regexr.com/3dmlr

我为什么应该使用第二个,如果第一个做相同的事情?

谢谢。

Wik*_*żew 5

什么是展开循环

请参阅此展开循环技术源:

此优化方法用于优化表格的重复替换(expr1|expr2|...)*。这些表达式并不罕见,并且在交替中使用另一个重复也可能导致超线性匹配。超线性匹配源自不确定性表达式(a*)*

展开循环技术基于以下假设:在大多数情况下,您会重复进行交替,哪种情况应该是最常见的,哪种情况是例外的。我们将第一个称为正常情况,将第二个称为特殊情况。展开循环技术的一般语法可以写成:

普通*(特殊普通*)*

因此,这是一种优化技术,其中的交替变成线性匹配的原子。

由于这些展开模式涉及较少的回溯,因此使它们非常有效。

当前场景

MINISTÉRIO[\s\S]*?PÁG是is的非展开模式MINISTÉRIO[^P]*(?:P(?!ÁG)[^P]*)*PÁG。请参阅演示(两者都保存有PCRE选项,以在上面的框中显示步骤数。各正则表达式引擎的正则表达式性能不同,但这将告诉您确切的性能差异)。在之后添加更多文本text:第一个正则表达式将开始需要完成更多步骤,第二个正则表达式仅在添加后显示更多步骤P。因此,在文本中您在已知部分使用的字符不常见的情况下,展开模式非常有效

请参阅我的答案中的量词之间.*?.*[^"]*+区别以了解延迟匹配的工作原理(您的用法与DOTALL修饰符在允许a 匹配换行符的语言中[\s\S]*?相同)。.*?.

绩效问题

惰性匹配模式是否总是缓慢且效率低下?并非总是如此。对于非常短的字符串,通常更好地使用惰性点匹配(1-10个符号)。当我们谈论长输入时,可能有前导定界符而没有尾随定界符,这可能导致过多的回溯,从而导致超时问题。

当您有可能很长的任意输入并且可能不匹配时,请使用展开模式。

当您的输入受到控制时,请使用惰性匹配,因为您知道总会有匹配项,某些已知的设置日志格式等。

奖励:通常展开的模式

  1. 贪婪的令牌

  2. 常规字符串文字("String\u0020:\"text\""):"[^"\\]*(?:\\.[^"\\]*)*"

  3. 多行注释正则表达式(/* Comments */):/\*[^*]*\*+(?:[^/*][^*]*\*+)*/

  4. @<...>@ 评论正则表达式: @<[^>]*(?:>[^@]*)*@