我有很多行包含美国总统卡特,布什,克林顿,奥巴马的名字.一些包含其中一个名称,一些包含2个,一些包含3个,其中一些包含所有4个(以任何顺序排列).
我知道如何寻找卡特和克林顿以及奥巴马 - >
:g/.*Carter\&.*Clinton\&.*Obama/p
Run Code Online (Sandbox Code Playgroud)
我知道如何寻找卡特和(克林顿或布什) - >
:g/.*Carter\&\(.*Clinton\|.*Bush\)/p
Run Code Online (Sandbox Code Playgroud)
(肯定有更好的方法)
但我无法想象如何搜索(我看了相关的问题),例如,布什和克林顿不卡特,甚至更少搜索,例如,布什和克林顿不(卡特奥巴马).
Pi *_*ort 52
要表示NOT,请使用否定断言\@!
.
例如,"不是布什"将是:
^\(.*Bush\)\@!
Run Code Online (Sandbox Code Playgroud)
或使用\v
:
\v^(.*Bush)@!
Run Code Online (Sandbox Code Playgroud)
重要提示:请注意领先^
.虽然如果你只使用正断言(一个匹配与其他匹配一样好)是可选的,但是需要锚定负断言(否则它们仍然可以在一行的末尾匹配).
翻译"布什与克林顿而不是(卡特或奥巴马)":
\v^(.*Bush)&(.*Clinton)&(.*Carter|.*Obama)@!
Run Code Online (Sandbox Code Playgroud)
One&Two&Three
Run Code Online (Sandbox Code Playgroud)
可互换:
(One)@=(Two)@=Three
Run Code Online (Sandbox Code Playgroud)
唯一的区别是\&
直接镜像\|
(应该更加明显和自然),而\@=
镜像Perl (?=pattern)
.
ZyX*_*ZyX 14
如果你想在vim之后使用Perl风格的正则表达式,请忘记\&
:它是一个vim特有的功能,因为vim也有前瞻功能,所以任何r1\&r2
都可以重写为\%(r1\)\@=r2
.但是前瞻性更好,因为它有一个负面版本,它们也可以在大多数Perl风格的正则表达式引擎中使用.您(Bush AND Clinton AND NOT (Carter OR Obama))
可以通过以下方式表达:
g/^\%(.*\%(Carter\|Obama\)\)\@!\%(.*Bush\)\@=.*Clinton/
Run Code Online (Sandbox Code Playgroud)
或者,非常神奇:
g/^\v%(.*%(Carter|Obama))@!%(.*Bush)@=.*Clinton/
Run Code Online (Sandbox Code Playgroud)
看到 :h /\@=
关于内部逻辑:前瞻就像分支:对于正则表达式(reg1)@=reg2
假设reg2
匹配位置N
(匹配从位置开始N
),正则表达式引擎检查是否reg1
也匹配此位置.如果没有,则丢弃该位置,并且正则表达式引擎尝试下一次可能的匹配reg2
.同为负前瞻,但与正则表达式引擎丢弃如果位置的差异reg1
确实匹配.
例:
正则表达式:(.b)@!a
.
字符串:aba
.
a
匹配位置0(aba
).尝试匹配前瞻:.
匹配a
(aba
)和b
匹配b
(),前瞻匹配,丢弃位置.aba
aba
a
a
匹配位置2().尝试匹配前瞻:matches (),但不匹配:没有符号,前瞻失败.结果:正则表达式匹配位置2.aba
.
a
aba
b