代码之家  ›  专栏  ›  技术社区  ›  Ben

匹配不后跟“bar”的“foo”实例

  •  1
  • Ben  · 技术社区  · 7 年前

    如何匹配字符串,其中“foo”后跟“bar”以外的内容(foo末尾有单词边界)?

    示例

    library(stringr)
    str_detect("foo 123", "\\bfoo\\b^(bar)")  # should be TRUE
    str_detect("foo", "\\bfoo\\b^(bar)")  # should be TRUE
    str_detect("foo bar", "\\bfoo\\b^(bar)")  # should be FALSE
    

    很明显我试过的, \\bfoo\\b^(bar) 不正确。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Ahmed Abdelhameed    7 年前

    如果前面有一个否定的展望,您可以使用如下内容:

    \bfoo\b(?!\W+bar)
    

    Regex101 demo

    显然,如果 \ 在R中是非法的,你需要逃离它,所以你要使用 \\bfoo\\b(?!\\W+bar) 相反。


    如果 bar 也必须是一个完整的单词,您可以添加一个额外的 \b 最后:

    \bfoo\b(?!\W+bar\b)
    

    Another demo

        2
  •  0
  •   Wiktor Stribiżew    7 年前

    在一般情况下,检测 foo 后面没有 bar (位于 )可以使用基R。 grep perl=TRUE 参数:

    x <- c("foo bar", "foo")
    grep("(?s)foo(?!.*bar)", x, perl=TRUE, value=TRUE)
    

    查看 R demo

    这个 (?!.*bar) 是一个 negative lookahead . 它只断言没有某种模式 之后 当前的regex引擎位置,即,如果没有匹配,则检查并返回true,否则返回false。因此,它不“使用”字符,regex引擎在输入字符串中保持相同的位置。在这个regex中,它是后面的位置 . 所以,就在这之后 ,regex引擎开始寻找 .* (任何字符,包括换行符(由于 DOTALL (?s) 内联修饰符),0次或多次重复),然后尝试匹配 酒吧 . 因此,如果有 酒吧 ,因为lookahead将返回,所以没有匹配项。

    要将这些单词作为整个单词匹配,请不要忘记 \b 在模式中每个单词的两端(如艾哈迈德在回答中所指出的)。

    注意:如果在 酒吧 使用特定的模式,而不是 * :

    foo(?!\s+bar) - no "bar" after "foo" separated with 1+ whitespaces from it
    foo(?!\W+bar) - no "bar" after "foo" separated with 1+ non-word chars from it
    foo(?!\w*bar) - no "bar" after "foo" in the same "word" (digits, letters, _)
    foo(?!\p{L}*bar) - no "bar" after "foo" in the same letter-word
    

    是的,不要忘记在R代码中使用两次转义反斜杠。