Regex R:(*跳过)(*失败)用于多个模式

Regex R:(*跳过)(*失败)用于多个模式,regex,r,boolean,Regex,R,Boolean,给定test(*SKIP)(*F)以及我的行出错的原因。您可以在第一个模式中添加\w*,以帮助引擎获得更多数据,告诉引擎ee或me可以出现在字符串的开头、中间或结尾 您可以使用这样的正则表达式: \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

给定
test(*SKIP)(*F)
以及我的行出错的原因。

您可以在第一个模式中添加
\w*
,以帮助引擎获得更多数据,告诉引擎
ee
me
可以出现在字符串的开头、中间或结尾

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

\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('\\w*[em]e\\w*(*SKIP)(?!)|e', '', test, perl=T)
或者正如@casimirithippolyte所指出的,在前面加上一个可选的“e”

根据评论更新了(使用量词(对于其他情况)):

注意:我决定使用
(?!)
而不是
(*F)
,后者也用于强制正则表达式失败

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

总的来说,语法可以写成
(*SKIP)(*FAIL)
(*SKIP)(*F)
(*SKIP)(?!)
这是
(*SKIP)(*F)
的正确解决方案:

,使用以下测试用例:

met
meet
eel
elm
degree
zookeeper
meee
仅匹配
elm
中的
e
degree
中的第一个
e
zookeeper
中的最后一个
e

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

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

对其他解决办法的分析 解决方案0 让我们以
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 这只会跳过带有
ee
me
的所有单词,这意味着它将无法匹配
度数
zookeeper
中的任何内容

解决方案2 与解决方案0类似的问题。当一行中有3个
e
时,前2个
e
mee?
匹配,第三个
e
可供匹配

解决方案3 这将丢弃直到最后一个
me
ee
的输入,这意味着在最后一个
me
ee
之前的任何有效
e
将不会匹配,就像
中的第一个
e
一样


不确定是否有解决方案,但正则表达式单独匹配了
“meet”
的第二个
“e”
,长度为1,如:
regexpr(((ee | me)(*SKIP)(*F)| e),test,perl=TRUE)
我需要在
gsub
中使用这一行,所以我不相信这是一个解决方案。我没有提出解决方案,只需提供
regexpr
为您正在使用的正则表达式提供的更多信息。在跳过“ee”和“me”之后,匹配仅在“meet”的第二个“e”上。这是因为首先找到了
me
(因为它比子字符串
mee
中的
ee
更位于字符串的左侧),因此,无法为子字符串
mee
找到
ee
,因为正则表达式已使用
me
子模式使用了前两个字母。解决方案是在您的模式中将
me
替换为
mee?
。请记住,正则表达式引擎从左到右逐字符搜索字符串。另外,不要忘记NFA正则表达式引擎(如R语言中使用的引擎)总是选择交替成功的第一个分支(DFA正则表达式引擎选择与最长子字符串匹配的分支)。您应该解释
(*失败)
(*F)
(?!)
^
meee
您的第二个正则表达式与最后一个
e
匹配
meeete
您的第一个正则表达式无法与最后一个
e
匹配
temeete
您的第二个正则表达式无法与第一个
e
匹配您的第一个正则表达式无法与最后一个
e
@nhahdh匹配,多亏了这一点。看到您的解决方案了吗n、 非常聪明的克利夫里不知道我们对一些甚至不需要回溯动词的东西很感兴趣。@hwnd:是的,OP在问题中提到了这一点,尽管我只是回答OP想知道的关于回溯动词解决方案的问题。
(?!)    # equivalent to ( (*FAIL) or (*F) - both synonyms for (?!) ), 
        # causes matching failure, forcing backtracking to occur
(?:me+|ee+)(*SKIP)(*FAIL)|e
met
meet
eel
elm
degree
zookeeper
meee
(ee|me)(*SKIP)(*F)|e
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`
\w*(ee|me)\w*(*SKIP)(*FAIL)|e
(?:ee|mee?)(*SKIP)(?!)|e
(?:^.*[me]e)(*SKIP)(*FAIL)|e