给定 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
中的 elm
, e
中的第一个 degree
和 e
中的最后一个 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
这将跳过所有带有
ee
和 me
的单词,这意味着它将无法匹配 degree
和 zookeeper
中的任何内容。Demo
解决方案2
(?:ee|mee?)(*SKIP)(?!)|e
与解决方案0类似的问题。当连续有3个
e
时,前2个e
被mee?
匹配,留下第三个e
进行匹配。解决方案3
(?:^.*[me]e)(*SKIP)(*FAIL)|e
这会将输入丢弃到最后一个
me
或 ee
,这意味着最后一个 e
或 me
之前的任何有效 ee
都不会匹配,就像 e
中的第一个 degree
。Demo
关于regex - R: (*SKIP)(*FAIL) 多个模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29639562/