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