我试图深入研究正则表达式并希望匹配条件,除非在同一个字符串中也找到了一些子字符串。我知道我可以使用两个grepl
语句(如下所示),但我想用一个正则表达式来测试这个条件,因为我推动了我的理解。让我们说我想匹配单词" dog"和"男人"使用"(dog.*man|man.*dog)"
(taken from here)但不是如果字符串包含子字符串" park"。我想我可以用(*SKIP)(*FAIL)
否定" park"但这不会导致字符串失败(如下所示)。
(*SKIP)(*FAIL)|
代码:
x <- c(
"The dog and the man play in the park.",
"The man plays with the dog.",
"That is the man's hat.",
"Man I love that dog!",
"I'm dog tired",
"The dog park is no place for man.",
"Park next to this dog's man."
)
# Could do this but want one regex
grepl("(dog.*man|man.*dog)", x, ignore.case=TRUE) & !grepl("park", x, ignore.case=TRUE)
# Thought this would work, it does not
grepl("park(*SKIP)(*FAIL)|(dog.*man|man.*dog)", x, ignore.case=TRUE, perl=TRUE)
答案 0 :(得分:6)
您可以使用锚定的先行解决方案(需要Perl样式的正则表达式):
grepl("^(?!.*park)(?=.*dog.*man|.*man.*dog)", x, ignore.case=TRUE, perl=T)
^
- 将模式锚定在字符串的开头(?!.*park)
- 如果park
存在,则匹配失败(?=.*dog.*man|.*man.*dog)
- 如果man
和dog
不存在,则匹配失败。另一个版本(更具可伸缩性),有3个预见:
^(?!.*park)(?=.*dog)(?=.*man)
答案 1 :(得分:3)
stribizhev已经answered this question,因为它应该接近:前瞻性负面。
我会为这个特殊问题做出贡献:
我对
(*SKIP)(*FAIL)
的理解有什么问题?
(*SKIP)
和(*FAIL)
是正则表达式控制动词。
(*FAIL)
或(*F)
(*FAIL)
与完全与具有空子模式的负前瞻相同:(?!)
。一旦正则表达式引擎在模式中获得该动词,它就会立即强制回溯。 <强> (*SKIP)
强>
当正则表达式引擎首次遇到此动词时,没有任何反应,因为它仅在回溯时达到。但是如果稍后失败,并且它从右到左到达(*SKIP)
,则回溯无法通过(*SKIP)
。它导致:
(*SKIP)
时的位置开始。这就是为什么这两个控制动词通常在一起(*SKIP)(*FAIL)
让我们考虑以下example:
.*park(*SKIP)(*FAIL)|.*dog
"That park has too many dogs"
" has too many dog"
<强>塔内:强>
That park has too many dogs || .*park(*SKIP)(*FAIL)|.*dog
/\ /\
(here) we have a match for park
the engine passes (*SKIP) -no action
it then encounters (*FAIL) -backtrack
Now it reaches (*SKIP) from the right -FAIL!
(*SKIP)
具有此特定行为。第二次尝试开始: That park has too many dogs || .*park(*SKIP)(*FAIL)|.*dog
/\ /\
(here)
Now, there's no match for .*park
And off course it matches .*dog
That park has too many dogs || .*park(*SKIP)(*FAIL)|.*dog
^ ^ -----
| (MATCH!) |
+---------------+
我如何匹配find“dog”&amp;的逻辑? “男人”而不是“停放”1个正则表达式?
使用stribizhev的解决方案!!为了兼容性,尽量避免使用控制动词,它们并没有在所有正则表达式中实现。但如果你对这些正则表达式奇怪感兴趣,还有另一个更强大的控制动词:(*COMMIT)
。它类似于(*SKIP)
,仅在回溯时起作用,除非它导致整个匹配失败(根本不会有任何其他尝试)。对于example:
+-----------------------------------------------+
|Pattern: |
|^.*park(*COMMIT)(*FAIL)|dog |
+-------------------------------------+---------+
|Subject | Matches |
+-----------------------------------------------+
|The dog and the man play in the park.| FALSE |
|Man I love that dog! | TRUE |
|I'm dog tired | TRUE |
|The dog park is no place for man. | FALSE |
|park next to this dog's man. | FALSE |
+-------------------------------------+---------+