重复交替组内的前瞻行为
Lookahead behaviour inside repeated alternation group
像 (?:(?=abc)|[abc])+
这样的正则表达式将匹配由 a
、b
和 c
组成的字符串,直到满足先行条件。
例如。对于字符串 acbababcaaa
它将匹配 acbab
- 停在第一个 abc
的前面,但如果它过于贪婪它可能会前进到字符串的末尾。
我们可以通过在模式末尾添加 $
来强制执行此操作 ((?:(?=abc)|[abc])+$
) - 现在它实际上匹配到字符串的末尾。
当我们现在将重复更改为所有格时 ((?:(?=abc)|[abc])++$
) - 它将匹配 bcaaa
- 因此第一个位置,前瞻无法再匹配。
谁能解释这些行为的原因?
当你强制引擎占有式前进时,它不再回溯到第一组 (?:...)
。
在看到 abc
之后,整个组都存在正前瞻引擎,并期望输入字符串结束 $
。它不存在,也无法回溯以尝试交替的另一侧,因此它完全失败,[abc]
之前使用的所有字符都被释放,指针被重置为整个模式的前一个起始位置的下一个字符。
你可以用原子组(?>(?=abc)|[abc])+$
来写它以更明确地表达差异。这个过程继续,只要它在输入字符串中看到 abc
后跟字符串结尾 $
.
就会失败
这就是 bcaaa
个字符在末尾匹配的原因,因为在 a
之后,在 bcaaa
被消耗之前,肯定不会发生前瞻。
像 (?:(?=abc)|[abc])+
这样的正则表达式将匹配由 a
、b
和 c
组成的字符串,直到满足先行条件。
例如。对于字符串 acbababcaaa
它将匹配 acbab
- 停在第一个 abc
的前面,但如果它过于贪婪它可能会前进到字符串的末尾。
我们可以通过在模式末尾添加 $
来强制执行此操作 ((?:(?=abc)|[abc])+$
) - 现在它实际上匹配到字符串的末尾。
当我们现在将重复更改为所有格时 ((?:(?=abc)|[abc])++$
) - 它将匹配 bcaaa
- 因此第一个位置,前瞻无法再匹配。
谁能解释这些行为的原因?
当你强制引擎占有式前进时,它不再回溯到第一组 (?:...)
。
在看到 abc
之后,整个组都存在正前瞻引擎,并期望输入字符串结束 $
。它不存在,也无法回溯以尝试交替的另一侧,因此它完全失败,[abc]
之前使用的所有字符都被释放,指针被重置为整个模式的前一个起始位置的下一个字符。
你可以用原子组(?>(?=abc)|[abc])+$
来写它以更明确地表达差异。这个过程继续,只要它在输入字符串中看到 abc
后跟字符串结尾 $
.
这就是 bcaaa
个字符在末尾匹配的原因,因为在 a
之后,在 bcaaa
被消耗之前,肯定不会发生前瞻。