鉴于test <- c('met','meet','eel','elm')
,我需要一行代码匹配任何不在'我'或'ee'的e.我写道(ee|me)(*SKIP)(*F)|e
,它确实排除了"遇见"和"鳗鱼",但没有"遇见".这是因为|
是独家还是?无论如何,有没有一个解决方案只能返回'榆树'?
为了记录,我知道我也可以做(?<![me])e(?!e)
,但我想知道解决方案是什么(*SKIP)(*F)
以及为什么我的线路是错误的.
这是正确的解决方案(*SKIP)(*F)
:
(?:me+|ee+)(*SKIP)(*FAIL)|e
Run Code Online (Sandbox Code Playgroud)
使用以下测试用例在regex101上演示:
met
meet
eel
elm
degree
zookeeper
meee
Run Code Online (Sandbox Code Playgroud)
只有e
in elm
,first e
in degree
和last e
in zookeeper
匹配.
因为e
in ee
是禁止的,所以禁止任何e
in,m
并禁止任何e
连续的子串e
.这解释了子模式(?:me+|ee+)
.
虽然我知道这种方法不可扩展,但它至少在逻辑上是正确的.
(ee|me)(*SKIP)(*F)|e
Run Code Online (Sandbox Code Playgroud)
我们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`
Run Code Online (Sandbox Code Playgroud)
问题是由于me
消耗了第一个e
,因此ee
无法匹配,第二个e
可用于匹配.
\w*(ee|me)\w*(*SKIP)(*FAIL)|e
Run Code Online (Sandbox Code Playgroud)
这将只是用ee
和跳过所有单词me
,这意味着它将无法匹配degree
和中的任何内容zookeeper
.
(?:ee|mee?)(*SKIP)(?!)|e
Run Code Online (Sandbox Code Playgroud)
与解决方案0类似的问题.当e
连续3 个时,前2个e
匹配mee?
,留下第3个e
可用于匹配.
(?:^.*[me]e)(*SKIP)(*FAIL)|e
Run Code Online (Sandbox Code Playgroud)
这会将输入丢弃到最后一个me
或者ee
,这意味着任何有效的数据都会e
在最后一个之前me
或者ee
不会匹配,就像e
在第一个中一样degree
.