给定 test <- c('met','meet','eel','elm') ,我需要一行代码来匹配不在“me”或“ee”中的任何 e。我写了 (ee|me)(*SKIP)(*F)|e ,它不排除“met”和“eel”,但不排除“meet”。这是因为 | 是独占的还是?无论如何,有没有只返回“elm”的解决方案?

作为记录,我知道我也可以做 (?<![me])e(?!e) ,但我想知道 (*SKIP)(*F) 的解决方案是什么以及为什么我的线路是错误的。

最佳答案

这是 (*SKIP)(*F) 的正确解决方案:

(?:me+|ee+)(*SKIP)(*FAIL)|e

Demo on regex101 ,使用以下测试用例:
met
meet
eel
elm
degree
zookeeper
meee

只匹配 e 中的 elme 中的第一个 degreee 中的最后一个 zookeeper

由于e中的ee被禁止,因此e之后的任何m都被禁止,连续e的子串中的任何e都被禁止。这解释了子模式 (?:me+|ee+)

虽然我知道这种方法不可扩展,但至少在逻辑上是正确的。

其他解决方案分析

解决方案 0
(ee|me)(*SKIP)(*F)|e

我们以 meet 为例:
meet        # (ee|me)(*SKIP)(*F)|e
^           # ^

meet        # (ee|me)(*SKIP)(*F)|e
  ^         #        ^

meet        # (ee|me)(*SKIP)(*F)|e
  ^         #               ^
            # Forbid backtracking to pattern to the left
            # Set index of bump along advance to current position

meet        # (ee|me)(*SKIP)(*F)|e
  ^         #                  ^
            # Pattern failed. No choice left. Bump along.
            # Note that backtracking to before (*SKIP) is forbidden,
            # so e in second branch is not tried

meet        # (ee|me)(*SKIP)(*F)|e
  ^         # ^
            # Can't match ee or me. Try the other branch

meet        # (ee|me)(*SKIP)(*F)|e
   ^        #                    ^
            # Found a match `e`

问题是由于 me 消耗了第一个 e ,因此 ee 无法匹配,留下第二个 e 可用于匹配。

解决方案1
\w*(ee|me)\w*(*SKIP)(*FAIL)|e

这将跳过所有带有 eeme 的单词,这意味着它将无法匹配 degreezookeeper 中的任何内容。

Demo

解决方案2
(?:ee|mee?)(*SKIP)(?!)|e

与解决方案0类似的问题。当连续有3个e时,前2个emee?匹配,留下第三个e进行匹配。

解决方案3
(?:^.*[me]e)(*SKIP)(*FAIL)|e

这会将输入丢弃到最后一个 meee ,这意味着最后一个 eme 之前的任何有效 ee 都不会匹配,就像 e 中的第一个 degree

Demo

关于regex - R: (*SKIP)(*FAIL) 多个模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29639562/

10-12 00:21