展开循环,何时使用

IT技术 javascript regex
2021-01-14 10:26:51

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

MINISTÉRIO[\s\S]*?PÁG

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

在这种情况下:

http://regexr.com/3dmlr

如果第一个做同样的事情,我为什么要使用第二个?

谢谢。

1个回答

什么是展开循环

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

这种优化技巧用于优化表格的重复交替(expr1|expr2|...)*这些表达式并不少见,在交替中使用另一个重复也可能导致超线性匹配。超线性匹配源于下限表达式(a*)*

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

正常*(特殊正常*)*

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

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

当前情景

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

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

性能问题

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

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

当你的输入被控制时使用惰性匹配,你知道总会有一个匹配,一些已知的设置日志格式,等等。

奖励:通常展开的模式

  1. 调和的贪婪令牌

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

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

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

我加了更多。通常,行为是相似的:展开的模式更快、更可靠,因为当模式与字符串不匹配时,它们会更优雅地失败。
2021-03-20 10:26:51
行。非常感谢你的处理
2021-03-24 10:26:51
现在我明白了!谢谢你 Wiktor :)
2021-04-01 10:26:51