regex - 有人可以解释这些正则表达式结果吗

标签 regex

我正在测试一些随机正则表达式,并发现了一些奇怪的结果。假设我们有正则表达式 (ab|(ba)*|a)* 它与 aba 不匹配,但如果我删除内部星号, (ab| (ba)|a)* 或者如果我切换术语的顺序,(a|ab|(ba)*)* 这两种情况现在匹配 aba.那么为什么会出现这样的情况呢?这与歧义或嵌套 * 有关吗?我知道这是一个奇怪的测试用例,内部 * 是多余的,但我只想了解这些结果。我使用 regex101.com 进行测试。

最佳答案

交替运算符 (|) 是短路的,并且将始终尝试匹配最左边的可能子模式,直到该子模式失败,此时它将尝试匹配下一个。只能匹配不重叠的模式。空字符串匹配会导致当前的贪婪模式结束,因为空字符串可以无限匹配,无论贪婪与否,继续这样做是没有意义的。贪婪并不一定意味着愚蠢。 :)

因此,在模式 (ab|(ba)*|a)* 和字符串 'aba' 的情况下,它将匹配来自字符串的开头。由于您在最外层捕获组 * 上使用贪婪量词,因此正则表达式将继续尝试与最外层捕获组进行更长的匹配。匹配迭代器将位于第三个字符,它将尝试匹配“ab”,但会失败。然后,当意识到它可能会与空字符串无限次匹配 (ba)* 时,它将结束匹配(不会捕获 (ba)* 的任何内容) > 而不尝试匹配最后一个替代模式a)并返回最外层重复捕获组的最后一次迭代。

现在,如果您切换与 (ab|a|(ba)*)* 等交替运算符链接的子模式的顺序,它将匹配整个字符串,因为匹配器能够使用 a 推进匹配迭代器,然后使用第三个替代子模式的最终空字符串匹配来完成匹配。

(ab|(ba)|a)* 也有效,因为第二个替代不能与空字符串匹配,所以一旦它失败匹配 ba,它成功地继续尝试匹配 a

另一种类似的修复方法是使用(ab|(ba)+|a)*。这将正确地导致第二个替代方案正确失败,而不是匹配它。

修复此问题的最后一种方法是使用字符串末尾的 anchor ,通常用 $ 表示。模式 (ab|(ba)*|a)*$ 能够在匹配第二个替代方案时正确​​失败,因为它意识到这样做永远不会到达字符串的末尾。它最终仍然会匹配第二个替代项,但只有在匹配迭代器遍历到字符串末尾之后。

这就是为什么您在最外层捕获组中只看到一个带有字符串'aba'的捕获。模式 (ba)* 将始终从索引 2-2(或任何空子字符串)开始匹配,然后结束当前匹配并阻止下一个 a匹配,但不会捕获任何内容,除非您的字符串中有一个显式的 'ba' 并且不与任何早期的替代项重叠。

关于regex - 有人可以解释这些正则表达式结果吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30146054/

相关文章:

regex - 如何匹配 RewriteCond 中的子目录?

Javascript 正则表达式流行语

php - 在 PHP 中使用正则表达式替换空格

ios - 如何转义正则表达式字符串

javascript - JQuery字符串替换特定字符

java - String.ReplaceAll 中的正则表达式

c# - 提取数据的正则表达式

在 Java 中工作的正则表达式在 Oracle 脚本中不起作用

c# - 简单的正则表达式匹配问题?

javascript - 用JS替换网页中的文字