有没有办法在vim正则表达式中做负面的预测?

时间:2014-01-15 21:20:14

标签: regex vim negative-lookahead

在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中以交互方式进行上述操作。)

5 个答案:

答案 0 :(得分:30)

你的尝试非常接近;你需要.* ,允许匹配与后来的不匹配之间的任意距离进入否定前瞻

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

虽然你的问题是关于前瞻性的,但我在寻找外观时发现了它。因此,我将解决方案发布到了lookbehind,以便其他人可以找到它。

如果您搜索的pattern2前面没有pattern1,那就是负面的背后搜索,请搜索:

\(pattern1\)\@<!pattern2

答案 3 :(得分:1)

我总是觉得很奇怪,您需要在vim中转义括号,因此我大多数时候都尝试使用{very magic}模式,并通过\v激活:

/\vabc(.*xyz)@!

答案 4 :(得分:0)

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

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

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

我喜欢它比“abc后跟任何没有跟随xyz的东西”更好,就像所提到的其他模式一样。