regex 如何对一个lookbehind正则表达式求反?

u7up0aaq  于 2023-08-08  发布在  其他
关注(0)|答案(2)|浏览(111)

另一篇关于R中正则表达式的负后向的文章,但我找不到我在这里做错了什么。
我有这些字符串:

test <- c("a %in% c('b', 'e')" , "case_when(a %in% c('b', 'e'))", "hello")

字符串
我想检测哪些字符串包含%in%,而前面没有case_when(。我可以用这个正则表达式找到哪些包含case_when(,然后是%in%

grepl("(?=.*case\\_when\\()(.*%in%)", test, perl = TRUE)
#> [1] FALSE  TRUE FALSE


所以我只需要否定这个lookbehind,我认为用<!替换=就足够了,但显然不是:

grepl("(?<!case\\_when\\()(.*%in%)", test, perl = TRUE)
#> [1]  TRUE  TRUE FALSE


预期输出为TRUE FALSE FALSE。我做错了什么?

monwx1rj

monwx1rj1#

.*是贪婪的。它匹配所有内容,* 包括 * case_when。也就是说,.*%in%匹配case_when(a %in%,并且由于该短语前面没有另一个case_when(,因此它被视为匹配。

case_when(a %in% c('b', 'e'))
^^^^^^^^^^^^
    '.*'

字符串
您可以用[^(]替换.,以便不匹配左括号,并使用(*SKIP)(*FAIL)习惯用法来排除不需要的内容。

case_when\(      # Match 'case_when('
[^(]*%in%        # followed by 0+ non-opening-bracket character and '%in'.
(*SKIP)(*FAIL)   # then skip and forfeit everything we just matched
|                # before matching
[^(]*%in%        # every other instance of `[^(]*%in%`.


试试on regex101.com
试试看:

test <- c("a %in% c('b', 'e')", "case_when(a %in% c('b', 'e'))", "hello")
grepl("case_when\\([^\\(]*%in%(*SKIP)(*FAIL)|[^\\(]*%in%", test, perl = TRUE)
#> [1]  TRUE FALSE FALSE


请注意,使用正则表达式解析(大概)R(一种非正则语言)很可能不是一个好的选择。

62lalag4

62lalag42#

?!--负向前看)不以"case_when"开始(^),并且包含"%in%"

grepl("^(?!case_when).*%in%.*", test, perl = T)

字符串
或者你可以把它分成两个匹配项(不检测"case_when" * 和 * 检测"%in%"):

!grepl("case_when", test, fixed = T) & grepl("%in%", test, fixed = T)

相关问题