在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中以交互方式进行上述操作。)
你的尝试非常接近;你需要拉动.*
,它允许匹配和后面的不匹配之间的任意距离进入负前瞻:
/abc\(.*xyz\)\@!
我想这是有效的,因为对.*
的所有可能匹配都尝试了不匹配,并且只有当所有分支都已用完时才宣布\@!
已经完成。
虽然你的问题是关于前瞻,但我在寻找后视时发现了它。因此,我将解决方案发布到了lookbehind,以便其他人可以找到它。
如果你搜索pattern2
之前没有pattern1
,那就是负面的背后,搜索:
\(pattern1\)\@<!pattern2
我总觉得很奇怪,你需要在vim中转义括号,所以我尝试在大多数情况下使用“非常神奇”的模式,用\v
激活:
/\vabc(.*xyz)@!
这适用于我/abc\(.*xyz\)\@!
我想我会把它写成/abc\(\(xyz\)\@!.\)*$
我不确定这是否比其他建议更快(我认为可能是因为它只测试每个位置一次)但它在概念上有意义:
“abc后跟任何不是xyz的东西,任何次数直到行结束”
我喜欢它比“abc跟随任何没有跟随xyz的东西”更好,就像在提到的其他模式中一样。