【问题标题】:Is there a way to do negative lookahead in vim regex?有没有办法在 vim 正则表达式中进行负前瞻?
【发布时间】:2014-02-04 13:46:30
【问题描述】:

在 Vim 中,有没有办法搜索与 abc 匹配的行,但后面的行不包含 xyz?所以以下几行将匹配:

The abc is the best
The first three letters are abc

以下内容不匹配:

The abc is the best but xyz is cheaper
The first three letters are abc and the last are xyz

我知道如下语法:

/abc\(xyz\)\@!

但这只会避免匹配abcxyz,而不是如果两者之间有任何东西,例如abc-xyz。使用

/abc.*\(xyz\)\@!

也不起作用,因为该行后面有很多位置 xyz 不匹配。

(我应该注意,在命令行上我会执行类似grep abc <infile | grep -v xyz 的操作,但我想在 Vim 中以交互方式执行上述操作。)

【问题讨论】:

    标签: regex vim negative-lookahead


    【解决方案1】:

    我总是觉得很奇怪,你需要在 vim 中转义括号,所以我大部分时间都尝试使用“非常神奇”的模式,用 \v 激活:

    /\vabc(.*xyz)@!
    

    【讨论】:

    • 很高兴知道这一点,我之前一直在 VIM-Regex 地狱
    【解决方案2】:

    虽然您的问题是关于前瞻的,但我在搜索后瞻时发现了它。因此,我将解决方案发布到后面,以便其他人可以找到它。

    如果您搜索pattern2 前面没有pattern1,即否定后向搜索,请搜索:

    \(pattern1\)\@<!pattern2
    

    【讨论】:

    • 这相当于 PCRE 中的(?!pattern1)pattern2
    【解决方案3】:

    我想我会写成/abc\(\(xyz\)\@!.\)*$

    我不确定这是否比其他建议更快(我认为可能是因为它只测试每个位置一次)但它在概念上是有意义的:

    "abc 后跟任何不是 xyz 的东西,任意次数直到行尾"

    我更喜欢上面提到的其他模式中的“abc 后跟不带 xyz 的任何内容”。

    【讨论】:

      【解决方案4】:

      您的尝试非常接近;您需要.* 拉到允许匹配和随后断言的不匹配之间的任意距离进入负前瞻

      /abc\(.*xyz\)\@!
      

      我想这是可行的,因为对 .* 的所有可能匹配都尝试了不匹配,并且只有当所有分支都用尽时,\@! 才会被声明为已完成。

      【讨论】:

      • 这相当于 Perl 引擎中的abc(?!.*xyz)
      • 这行得通,因为前瞻简单从当前位置启动另一个全面搜索模式,并使用结果来决定是否继续(取决于前瞻是否正面或负面)。
      • 另见:help perl-patterns。对于前面没有pattern1pattern2,即否定后视,搜索\(pattern1\)\@&lt;!pattern2
      • 这可能已经过时了 - 但在我看来,上述解决方案不适用于像xyzabc 这样的字符串。 OP 指出一行中不应有 xyz anywhere 。对我有用的是强制捕获整行:^(?!.*xyz).*abc(?!.*xyz)(不是vim 格式)。见RegExr
      • 这帮助我在 Terraform 计划中搜索变更线 /\("[^"]*"\) =&gt; \(\1\)\@!
      【解决方案5】:

      这对我有用/abc\(.*xyz\)\@!

      【讨论】:

        猜你喜欢
        • 2018-02-05
        • 2020-09-09
        • 2021-10-11
        • 2011-10-14
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多