鉴于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)
只有ein elm,first ein degree和last ein zookeeper匹配.
因为ein ee是禁止的,所以禁止任何ein,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.