1

当 RegEx 引擎到达 RegEx 中的多个环视部分时,它们是如何在内部工作的。

我已经阅读了这篇优秀的文章,但它不包括环视。任何人都可以用类似的方法大致解释一下环视(负面,正面,后面,向前)机制吗?

(我也很想知道引擎如何解释以下正则表达式:(RegExs 是不同的正则表达式字符串,可能是可变大小的,即包含+*

RegEx (?<!RegEx)(?<=RegEx)(?!RegEx)(?=RegEX) RegEx (?<!RegEx)(?<=RegEx)(?!RegEx)(?=RegEx)  RegEx

,我不想知道与它们匹配的内容,但我想知道引擎如何与它们匹配,它们只是示例。谢谢

NFA(非确定性有限自动化)图或任何类似的图对于说明该主题非常有用。

请不要让我参考regular-expressions.info,我已经读过了!它只是使用了两个非常简单的例子,我想大致了解引擎机制。

4

1 回答 1

1

Lookahead 很简单:当引擎遇到一个lookahead 表达式时,它会保存当前位置并正常检查是否匹配。如果不是,则返回失败(允许引擎检查正则表达式早期部分的其他选项)。如果是,它会恢复保存的位置并继续检查正则表达式的其余部分。

向后看更难。在 Python 中,对它们有一个限制,即它们必须是固定大小的。这使得评估变得容易:当遇到它时,检查前面的 [width] 字符是否与表达式匹配,其余的就像前瞻一样工作。如果你不使用这个固定大小的限制,评估会变得慢很多。这并不意味着算法变得复杂:它可以简单地尝试当前位置之前的所有字符串(它之前的 0 个字符、它之前的 1 个字符、它之前的 2 个字符等,直到有一个匹配,或者到达字符串的开头)。

至于顺序,正则表达式默认是贪婪的。这意味着在类似 的表达式中.*(s?)(s?)永远不会匹配任何内容,因为如果有 s,它已经被 匹配了.*。如果您不想要这个,请在​​ or?之后添加一个。*+

现在到你的例子:

  • /.*a(?=.*)/匹配任何内容,包括最后一个a(它是贪婪的)。(?=.*)总是匹配,所以它毫无价值:如果省略,正则表达式是相同的。
  • /.*a(?!a*)/从不匹配任何东西:否定前瞻中的表达式始终匹配(如果只是“0 次a”)。由于它是负数,这意味着前瞻总是失败。
  • /.*a(?=[^a]*)(?=[x])(?![c]*)/从不匹配任何东西。引擎将首先尝试.*a匹配所有内容,包括最后一个a. 这之后永远不会有另一个a,因此第一次先行总是成功(仅第一次)。如果后面没有,则下一个前瞻将失败x(注意括号在那里没有用;[x]与 相同x)。如果失败,它将尝试更短的字符串 for .*a,直到(第一个和)第二个前瞻匹配。请注意,如果第二个匹配,第一个前瞻总是匹配,所以它没有用。但是,第三个前瞻破坏了这一切:([c]*与 相同c*)总是匹配(在任何位置,您都可以说“这个空字符串是字符 c 的 0 倍的列表”),这意味着否定前瞻总是失败。

您可能会发现有趣的是,如果模式是非贪婪的,会发生什么。例如,/.*?a/将匹配包含a, 直到并包括a字符串中的第一个(而不是最后一个)的任何内容。

于 2012-11-24T10:21:56.060 回答