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

问题描述 投票:24回答:5

在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
5个回答
30
投票

你的尝试非常接近;你需要拉动.*,它允许匹配和后面的不匹配之间的任意距离进入负前瞻:

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

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


3
投票

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

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

\(pattern1\)\@<!pattern2

3
投票

我总觉得很奇怪,你需要在vim中转义括号,所以我尝试在大多数情况下使用“非常神奇”的模式,用\v激活:

/\vabc(.*xyz)@!

2
投票

这适用于我/abc\(.*xyz\)\@!


0
投票

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.