R:(* SKIP)(* FAIL)用于多种模式

时间:2015-04-15 00:19:21

标签: regex r boolean

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

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

3 个答案:

答案 0 :(得分:5)

这是(*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都被禁止,并且连续{{1}的子字符串中的任何e都被禁止} 禁止。这解释了子模式e

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

其他解决方案的分析

解决方案0

(?:me+|ee+)

我们以(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可用于匹配。

解决方案1 ​​

e

这只会跳过\w*(ee|me)\w*(*SKIP)(*FAIL)|e ee的所有字词,这意味着它无法匹配medegree中的任何字词。

Demo

解决方案2

zookeeper

与解决方案0类似的问题。当一行中有3 (?:ee|mee?)(*SKIP)(?!)|e 时,前{2} ee匹配,第三mee?可用于匹配

解决方案3

e

这会将输入丢弃到最后(?:^.*[me]e)(*SKIP)(*FAIL)|e me,这意味着在最后eee之前的任何有效me都不会匹配,就像ee中的第一个e一样。

Demo

答案 1 :(得分:4)

您需要前/后边界强制正则表达式引擎不重试子字符串。

gsub('\\w*[em]e\\w*(*SKIP)(?!)|e', '', test, perl=T)

或者@CasimiretHippolyte指出 - 前面有一个可选的&#34; e&#34; ...

gsub('(?:ee|mee?)(*SKIP)(?!)|e', '', test, perl=T)
每次评论

更新(使用量词(用于其他案例)):

gsub('[em]e+(*SKIP)(?!)|e', '', test, perl=T)

注意:我决定使用(?!)代替(*F),这也用于强制正则表达式失败。

(?!)    # equivalent to ( (*FAIL) or (*F) - both synonyms for (?!) ), 
        # causes matching failure, forcing backtracking to occur

总体而言,语法可以写为(*SKIP)(*FAIL)(*SKIP)(*F)(*SKIP)(?!)

答案 2 :(得分:3)

您可以在第一个模式中添加\w*,以便为引擎提供更多数据,告知eeme可以出现在字符串的开头,中间或末尾。< / p>

你可以使用这样的正则表达式:

\w*(ee|me)\w*(*SKIP)(*FAIL)|e

R正则表达式,

> test <- c('met','meet','eel','elm')
> gsub("\\w*(?:ee|me)\\w*(*SKIP)(*FAIL)|e", "fi", perl=TRUE, test)
[1] "met"  "meet" "eel"  "film"

> gsub('(?:^.*[me]e)(*SKIP)(*FAIL)|e', 'fi', test, perl=T)
[1] "met"  "meet" "eel"  "film"

<强> Working demo

enter image description here