vim 的正向和负向预查
在 Vim 的正则表达式中,预查(Lookaround) 是一种“断言”,用于匹配某个位置前后是否满足特定条件,但不消耗字符(即匹配结果中不包含预查括号内的内容)。
Vim 支持四种预查,分为正向/负向和向前/向后两个维度。以下是关键关键字和语法:
1. 核心语法关键字
| 类型 | 中文名称 | 英文术语 | Vim 语法 | 含义 |
|---|---|---|---|---|
| 正向预查 | 正向肯定预查 | Positive Lookahead | \@= |
匹配当前位置之后必须出现的内容 |
| 负向预查 | 正向否定预查 | Negative Lookahead | \@! |
匹配当前位置之后****不能出现的内容 |
| 反向预查 | 反向肯定预查 | Positive Lookbehind | \@<= |
匹配当前位置之前必须出现的内容 |
| 反向预查 | 反向否定预查 | Negative Lookbehind | \@<! |
匹配当前位置之前****不能出现的内容 |
注意:Vim 的正则语法与常见的 PCRE(如 Python、JavaScript 中的
(?=...))不同。Vim 将断言操作符放在被检查模式的后面。
2. 详细用法与示例
A. 向前预查 (Lookahead) - 检查右边
用于判断当前匹配内容的后面是什么。
-
正向 (
\@=):- 场景:匹配后面跟着 "bar" 的 "foo"。
- Vim 正则:
foo$bar$\@= - 解释:匹配 "foo",前提是它后面紧跟着 "bar"。最终只选中 "foo"。
- 对比 PCRE:
foo(?=bar)
-
负向 (
\@!):- 场景:匹配后面不跟着 "bar" 的 "foo"。
- Vim 正则:
foo$bar$\@! - 解释:匹配 "foo",前提是它后面不是 "bar"。
- 对比 PCRE:
foo(?!bar)
B. 向后预查 (Lookbehind) - 检查左边
用于判断当前匹配内容的前面是什么。
-
正向 (
\@<=):- 场景:匹配前面是 "foo" 的 "bar"。
- Vim 正则:
$foo$\@<=bar - 解释:匹配 "bar",前提是它前面紧跟着 "foo"。最终只选中 "bar"。
- 对比 PCRE:
(?<=foo)bar
-
负向 (
\@<!):- 场景:匹配前面不是 "foo" 的 "bar"。
- Vim 正则:
$foo$\@<!bar - 解释:匹配 "bar",前提是它前面不是 "foo"。
- 对比 PCRE:
(?<!foo)bar
3. 重要注意事项
-
位置差异:
- 通用正则(PCRE):操作符在括号前,如
(?=pattern)。 - Vim:操作符在括号后,如
$pattern$\@=。 - 记忆技巧:Vim 的逻辑是“先写出要检查的模式
$pattern$,然后声明对这个模式进行什么操作\@=”。
- 通用正则(PCRE):操作符在括号前,如
-
定长限制 (Lookbehind only):
- 在旧版本的 Vim 或某些配置下,向后预查(
\@<=和\@<!)内部的模式必须是定长的(Fixed width)。 - 例如:
$ab$\@<=c是合法的(长度为2)。 - 例如:
$a*$\@<=c通常是非法的(因为a*长度不定),但在较新的 Vim 版本(支持无限回溯引擎时)可能允许,或者需要使用\&等技巧变通。如果报错,请尝试重写逻辑或使用向前预查。
- 在旧版本的 Vim 或某些配置下,向后预查(
-
组合使用:
你可以组合多个预查来实现复杂逻辑。- 例子:匹配既不在 "start" 后也不在 "end" 前的 "middle"。
$start$\@<!middle$end$\@!
4. 快速总结表
| 你想检查... | 条件是“必须有” | 条件是“不能有” |
|---|---|---|
| 右边 (后面) | $pattern$\@= |
$pattern$\@! |
| 左边 (前面) | $pattern$\@<= |
$pattern$\@<! |
这些关键字是 Vim 高级文本处理(如复杂的查找替换 :s 或高亮匹配 :match)的核心工具。

浙公网安备 33010602011771号