/
/{pattern}[/]<CR> 正向搜索 {pattern} 第 [count] 次匹配。
exclusive 开动作。
/{pattern}/{offset}<CR> 正向搜索 {pattern} 第 [count] 次匹配并根据 {offset}
跳转上下若干行。
linewise 行级动作。
/<CR>
/<CR> 正向搜索上次搜索模式 last-pattern 的第 [count] 次匹
配,沿用上次偏移。
//{offset}<CR> 正向搜索上次搜索模式 last-pattern 的第 [count] 次匹
配,使用新偏移 {offset} 。{offset} 为空时不带偏移。
?
?{pattern}[?]<CR> 反向搜索 {pattern} 第 [count] 次匹配。
exclusive 开动作。
?{pattern}?{offset}<CR> 反向搜索 {pattern} 第 [count] 次匹配并根据 {offset} 跳
转上下若干行。
linewise 行级动作。
?<CR>
?<CR> 反向搜索上次搜索模式 last-pattern 的第 [count] 次匹
配,沿用上次偏移。
??{offset}<CR> 反向搜索上次搜索模式 last-pattern 的第 [count] 次匹
配,使用新偏移 {offset} 。{offset} 为空时不带偏移。
n
n 重复执行上次 / 或 ? 搜索 last-pattern [count]
次 (忽略原计数)。如果执行完毕后光标不移动,再重复执行
[count] + 1 次。
N
N 反方向重复执行上次 / 或 ? 搜索 last-pattern
[count] 次 (忽略原计数)。
star E348 E349
* 正向搜索光标附近单词第 [count] 次匹配。搜索目标依次选
取:
1. 光标所在关键字 'iskeyword'
2. 当前行内光标后方首个关键字
3. 光标所在非空白字符序列
4. 当前行内光标后方首个非空白字符序列
搜索时,相当于 /\<keyword\> ,只搜索整词。
exclusive 开动作。
受 'ignorecase' 选项影响,不考虑 'smartcase'。
#
# 类似 "*",但反向搜索。也可用英磅符号 (字符值 163 £)。
如果按 "#" 键产生退格效果,请在启动 Vim 前执行
"stty erase <BS>" (<BS> 代表按 CTRL-H 或实际退格键)。
gstar
g* 类似 "*",但不再自动包裹单词边界 \< 和 \> ,也能匹
更长单词的一部分。
g#
g# 类似 "#",但不再自动包裹单词边界 \< 和 \> ,也能匹
配更长单词的一部分。
gd
gd 跳转 (goto) 到光标所在局部变量的声明 (declaration) 位
置。专为 C 代码设计,对其他语言的支持并不可靠。
首先,Vim 会搜索当前函数的起始处,相当于 [[ 。不成功
则停在文件首行。成功则反向搜索空白行。
然后,从该处开始,正向搜索光标所在关键字,行为类似
* ,但会跳过注释行 (见 'comments' 选项)。
注意 Vim 不会做语法分析,仅做文本关键字匹配,因此无法
保证绝对可靠。如果也需要搜索头文件中的匹配,可见
include-search 一节列出的命令。
本命令执行后,可用 n 搜索下一处匹配 (总是假定正向)。
gD
gD 跳转 (goto) 到光标所在全局变量的声明 (Declaration) 位
置。类似 gd ,但搜索总是从文件首行开始。
1gd
1gd 类似 gd ,但忽略在光标前已闭合 {} 块里的匹配。
1gD
1gD 类似 gD ,但忽略在光标前已闭合 {} 块里的匹配。
CTRL-C
CTRL-C 中止当前正在执行的 (搜索) 命令。MS-Windows 上请改用
CTRL-Break dos-CTRL-Break 。
普通模式下,会取消当前正在等待后续按键的命令。
启动 Vim 时标准输出被重定向,且没有已修改缓冲区时,会
直接退出 Vim。方便执行 "vim file | grep word" 之类命令
的用户能提前退出 (也可盲打 :qa<CR> )。
带 popup-filter 的弹窗打开时,会关闭该弹窗。
:noh :nohlsearch
:noh[lsearch] 临时关闭 'hlsearch' 匹配高亮。再次执行搜索命令或手动置
位 'hlsearch' 选项时,高亮会自动恢复。
在自动命令中执行时,本命令效果会在自动命令退出时自动失
效,因为自动命令执行期间,搜索相关状态会被自动保存并恢
复 autocmd-searchpat 。
在用户函数中执行本命令也会如此 function-search-undo 。
打开 'incsearch' 选项后,输入搜索模式时会实时预览匹配文本。仍需按下 <CR> 完成
搜索命令,光标才会真正跳转到匹配位置。按下 <ESC> 会放弃本次搜索。
nohlsearch-auto
打开 'hlsearch' 选项后,最近搜索模式的所有匹配项都会保持高亮。可用
:nohlsearch 命令临时关闭,也可借助 nohlsearch 插件自动暂停高亮。见
nohlsearch-install 。
'shortmess' 不包含 "S" 标志位时,Vim 会自动显示光标所在匹配项索引。格式如下:
[1/5] 共 5 处匹配,光标在第一处。
[1/>99] 匹配总数超过 99 条,光标在第一条。
[>99/>99] 匹配总数超过 99 条,光村在第 99 条之后。
[?/??] 因搜索超时终止统计,总数未知。
注意: 统计匹配项时,不考虑偏移。
如果无匹配项,报错: E486 找不到模式
在 Vim9 脚本里,执行 :global 时如果无匹配会报错 E486,而执行 :vglobal 时
如果所有行都匹配会报错: E538 每行都匹配表达式
老式脚本里,为兼容 Vi,这两条命令会分别输出普通消息 "找不到模式" 或 "每行都匹
配表达式" 而非报错。
:s 命令可加 "e" 标志位屏蔽报错 :s_flags 。
search-options
以下选项影响 Vim 搜索行为:
'hlsearch' 高亮匹配内容
'ignorecase' 搜索时忽略大小写
'imsearch' 输入搜索模式时启用 IME
'incsearch' 输入模式期间实时预览已输入部分的匹配内容
'maxsearchcount' 搜索计数显示上限 shm-S
'shortmess' 抑制回绕信息 shm-s ;抑制搜索计数显示 shm-S
'smartcase' 模式含大写字母时,自动忽略 'ignorecase'
'wrapscan' 搜索到达文件末尾后,从文件开头继续搜索
search-offset {offset}
以上命令搜索特定模式。而 / 和 ? 命令可额外指定偏移。分为行偏移和字符偏移。
偏移用于指定找到匹配后,光标相对于该匹配的位置:
[num] 下移 [num] 行,停在首列
+[num] 下移 [num] 行,停在首列
-[num] 上移 [num] 行,停在首列
e[+num] 匹配结束 (end) 位置向右 [num] 个字符
e[-num] 匹配结束 (end) 位置向左 [num] 个字符
s[+num] 匹配开始 (start) 位置向右 [num] 个字符
s[-num] 匹配开始 (start) 位置向左 [num] 个字符
b[+num] 同 s[+num] (助记: begin 也是开始)
b[-num] 同 s[-num] (助记: begin 也是开始)
;{pattern} 接续执行新一轮搜索,见 //;
给出 '-' 或 '+' 但省略 [num] 时,缺省数值为 1。
使用 'e' 偏移时,搜索会成为 inclusive 闭动作 (包含光标到达字符)。
示例:
模式 光标位置
/test/+1 "test" 下一行行首
/test/e "test" 最后一个 't' 上
/test/s+2 "test" 里的 's' 上
/test/b-3 "test" 起始位置向左三个字符
任意操作符后搭配 / 或 ? 命令时,选区范围是搜索跳转前后光标位置之间的文本。
使用行偏移时,则选中两位置之间全部整行。
用模式搜索并用其他单词修改匹配的演示:
/foo<CR> 搜索 "foo"
c//e<CR> 修改至匹配尾
bar<Esc> 输入替换文本
//<CR> 跳转到下一处匹配开头
c//e<CR> 修改至匹配尾
beep<Esc> 输入替换文本
等等。
//; E386
有一种很特别的偏移,是 ';' 后接另一条搜索命令。例如:
/test 1/;/test
/test.*/+1;?ing?
其中第一例会先向后搜索 "test 1",再在该位置之后继续搜索第一个 "test"。
相当于接连执行两次搜索命令,不同之处在于:
- 可用于操作符之后,整体作为单次动作。
- 后续 n 或 N 命令的方向基于首条搜索。
- 任意一段匹配失败时,光标保持原位不动。
last-pattern
Vim 会保存最近的搜索模式和偏移。可反复使用,复用时可按需调整搜索方向和计数。
注意 Vim 会保存两套模式: 一套用于普通搜索命令 ( / 、 ? ),一套用于替代命令
:s 。用户指定空模式时,优先使用前次搜索模式。但如果没有,改用前次替代模式。
前次搜索模式会绑定当时的 'magic' 选项设定。后续修改 'magic',不会改变原有模式
的解析规则。'ignorecase' 选项则不然。后续修改 'ignorecase' 会直接改变原有模式
的匹配结果。
开启 'hlsearch' 选项后,所有前次搜索模式的匹配项都会高亮。
要清除前次搜索模式:
:let @/ = ""
其效果并不是将该模式设为空串 (因为空串会匹配全部文本),而是彻底清空,如同则启
动 Vim 时的状态。
搜索会自动跳过光标原地不动的匹配项。下一轮搜索的起始位置取决于 'cpoptions' 选
项的 'c' 标志位 ( cpo-c ),打开时从跳过的匹配文本之后开始,关闭时则从光标下一
个字符开始。示例:
包含 'c' 标志位: "/..." 前进 1 至 3 个字符
不包含 'c' 标志位: "/..." 前进 1 个字符
包含 'c' 标志位之所以结果不确定,是因为搜索机制是从行首开始搜索,跳过所有可能
匹配项,直到找到越过光标位置的匹配为止,而非从光标处开始搜索。
反向搜索时, 'cpoptions' 里包含 'c' 标志位时同样应用上述机制,从行首开始搜索,
使用光标位置前的最后一处匹配。
在 Vi 里执行 :tag 命令跳转标签时使用的搜索模式会覆盖前次搜索模式。Vim 缺省保
留原有前次搜索模式,除非 'cpoptions' 选项中包含 't' 标志位 ( cpo-t ) 以使用 Vi
兼容行为。无论如何,标签命令搜索模式总会存入搜索历史记录。
开启 'wrapscan' 选项 (缺省) 时,搜索触底会折返文件开头继续搜索。否则,反向搜索
会停在文件开头;正向搜索会停在文件结尾。如果该选项开启但无匹配,会报错 "找不到
模式" 且光标原地不动。取决于搜索方向,搜索折返时会分别提示: "已查找到文件结
尾,再从开头继续查找" 或 "已查找到文件开头,再从结尾继续查找"。提示消息可通过
'shortmess' 选项里包含 's' 标志位 ( shm-s ) 关闭。提示文本使用 'w' 高亮场景
(译者注: 见 'highlight',也可修改 hl-WarningMsg ) (终端缺省: standout )。
而如果该选项关闭但无匹配,取决于搜索方向,会分别报错 "已查找到文件结尾仍找不
到" 或 "已查找到文件开头仍找不到"。
search-range
可通过 \%>l 这类项目限定 / 命令在指定行范围内搜索。例如,要在第 200-299 行
搜索单词 "limit":
/\%>199l\%<300llimit
另见 /\%>l 。
另一种方案是带 'c' 标志位的 :substitute 命令 ( :s_c )。例如:
:.,300s/Pattern//gc
从当前行到第 300 行逐一匹配 "Pattern"。每次匹配会提示按键。按 'q' 终止搜索;按
'n' 跳到下一处匹配。
"*"、"#"、"g*" 和 "g#" 命令会按以下顺序选取光标附近的单词,排前者优先:
- 光标所在关键字 'iskeyword'。
- 当前行内光标后方首个关键字。
- 光标所在字串 ( WORD )。
- 当前行内光标后方首个字串。
关键字只能包括字母和 'iskeyword' 中列出的字符。字串 (WORD) 可包括任意连续非空
白 (<Tab> 或 <Space>) 字符。
备注 用十指打字的指法助记提示: "#" 在左手中指,向左用于反向搜索;"*" 在右手中
指,向右用于正向搜索 (键盘布局不同可能略有差异)。
E956
极罕见情况下,正则表达式会递归调用。例如,在执行长耗时模式匹配期间,在通道上检
查消息时,触发了使用模式搜索的回调或自动命令。多数此类场景可正常运行,但如果同
一正则模式被二次调用,会报错 (译者注: 内部模式对象包含状态,不可重用)。一般情
况下,此错误意味着所用模式有缺陷。
regular-expression regexp Pattern
E383 E476
头一道菜已经在用户手册的第 27 章 usr_27.txt 上过了。
/bar /\bar /pattern
1. 模式 (pattern) 由 "\|" 分隔开的一个或多个分支 (branch) 组成。只需匹配其中任
意一个分支即可。例如: "foo\|beep" 匹配 "foo" 或 "beep"。多分支同时匹配时,
优先选用靠前的分支。
pattern ::= branch
或 branch \| branch
或 branch \| branch \| branch
依此类推
/branch /\&
2. 分支由 "\&" 分隔开的一个或多个邻接 (concat) 组成。必须保证前面所有项在同一
位置同时匹配,最终只捕获最后一项邻接的匹配结果。的邻接也在同样位置匹配。例
如:
"foobeep\&..." 匹配 "foobeep" 中的 "foo"。
".*Peter\&.*Bob" 匹配同时包含 "Peter" 和 "Bob" 的行,匹配结果以 "Bob"
结尾。
branch ::= concat
或 concat \& concat
或 concat \& concat \& concat
依此类推
/concat
3. 邻接由一或多个相邻组件 (piece) 组成。从前到后依次接续匹配。例如: "f[0-9]b"
先匹配 "f",再匹配单个数位,最后匹配 "b"。
concat ::= piece
或 piece piece
或 piece piece piece
依此类推
/piece
4. 组件是单个原子 (atom),后跟可选倍数项 (multi),用来控制该原子匹配次数。例
如: "a*" 匹配零或多个 "a": "","a","aa" 等。参见 /multi 。
piece ::= atom
或 atom multi
/atom
5. 原子种类繁多。多数原子只匹配单个字符,常见为普通字符或字符类。也可用圆括号
将模式封装为单个原子。特别说明,"\z(\)" 构造仅用于语法高亮。
atom ::= ordinary-atom /ordinary-atom
或 \( pattern \) /\(
或 \%( pattern \) /\%(
或 \z( pattern \) /\z(
/\%#= two-engines NFA
Vim 包含两套正则表达式引擎:
1. 老式回溯引擎,支持全部功能。
2. 新式 NFA 引擎,多数模式速度更快,但少数模式会变慢。
E1281
Vim 会自动择优选择引擎。如需手动强制指定,在模式开头加入以下前缀:
\%#=0 强制自动选择。仅在 'regexpengine' 非零时生效。
\%#=1 强制使用老式引擎。
\%#=2 强制使用 NFA 引擎。
也可通过 'regexpengine' 选项切换缺省引擎。
E864 E868 E874 E875 E876 E877 E878
如果强制选择 NFA 引擎,但模式遇到尚未实现的语法,整个匹配会直接失效。该用法一
般只用于调试 Vim。
字母等普通字符在模式中按本义出现时,只匹配自身。但在前面加上反斜杠时,这些字符
具备特殊含义。如 "a" 匹配字母 "a",而 "\a" 匹配任意字母。
而特殊字符本身自带特殊语义。在前面加上反斜杠时,反而会匹配字符自身。如 "." 匹
配任意字符,而 "\." 只匹配句号。
字符是否代表其本义取决于 'magic' (魔术性) 选项。每个字符在该选项开关时具体含义
请查看其具体条目,见下。
建议总是置位 'magic' 选项,仅为 Vi 兼容才会关闭。为完整性起见,以下会提到
'nomagic' 时的效果,但不推荐日常使用。
/\m /\M
使用 "\m" 项使后续内容强制按 'magic' 方式解析。忽略 'magic' 选项值。
使用 "\M" 项使后续内容强制按 'nomagic' 方式解析。
/\v /\V
使用 "\v" 项使后续内容中除数位字母下划线 ('0'-'9'、'a'-'z'、'A'-'Z' 和 '_')
外,其他字符都启用特殊含义: "超魔术"。
使用 "\V" 项使后续内容中只有反斜杠与搜索终止符 (通常为 / 或 ?) 有特殊含义:
"超非魔术"。
示例:
在: \v \m \M \V 之后,会匹配
'magic' 'nomagic'
a a a a 'a' (按本义)
\a \a \a \a 字母字符
. . \. \. 任意字符
\. \. . . 句号 (按本义)
$ $ $ \$ 行尾
* * \* \* 前导原子的任意次重复
~ ~ \~ \~ 最近替代字符串
() \(\) \(\) \(\) 构成分组,封装为单个原子
| \| \| \| 分支分隔符,本身不匹配任何值
\\ \\ \\ \\ 反斜杠 (按本义)
\{ { { { '{' (按本义)
{仅 Vim 支持 \m,\M,\v 和 \V}
要使整个模式不受 'magic' 选项影响,在模式开头加上 "\m" 或 "\M"。
(译者注: 魔术性总览
超非魔术模式: 为特殊字符
非魔术模式: ^ $ 为特殊字符
魔术模式: ^ $ * . [ ~ 为特殊字符
超魔术模式: ^ $ * . [ ~ ( ) { % + = ? @ < > & | 为特殊字符
备注:
1. "\" 和搜索终止符 (取决于所用命令, / 或 ? ) 总为特殊字符。
2. 以下字符只有在特定位置才是特殊字符:
* "^" 出现在模式开头或 "\|"、"\("、"\%("、"\n" 之后
* "$" 出现在模式末尾或 "\|"、"\)"、"\n" 之前
* "*" 不出现在模式开头且不紧跟在 "^" 之后
)
E865 E866 E867 E869
倍数项一览。 /multi E61 E62
具体解释和示例见下,点击链接即可。 E64 E871
倍数
'magic' 'nomagic' 前导原子匹配次数
/star * \* 0 或更多 尽可能多
/\+ \+ \+ 1 或更多 尽可能多
/\= \= \= 0 或 1 尽可能多
/\? \? \? 0 或 1 尽可能多
/\{ \{n,m} \{n,m} n 到 m 尽可能多
\{n} \{n} n 准确
\{n,} \{n,} 最少 n 尽可能多
\{,m} \{,m} 0 到 m 尽可能多
\{} \{} 0 或更多 尽可能多 (同 *)
/\{- \{-n,m} \{-n,m} n 到 m 尽可能少
\{-n} \{-n} n 准确
\{-n,} \{-n,} 最少 n 尽可能少
\{-,m} \{-,m} 0 到 m 尽可能少
\{-} \{-} 0 或更多 尽可能少
E59
/\@> \@> \@> 1 要求完整模式匹配 (防止回溯)
/\@= \@= \@= 无 要求正向匹配,但不消耗字符 /zero-width
/\@! \@! \@! 无 要求正向 不 匹配,不消耗字符 /zero-width
/\@<= \@<= \@<= 无 要求反向匹配,但不消耗字符 /zero-width
/\@<! \@<! \@<! 无 要求反向 不 匹配,不消耗字符 /zero-width
普通原子一览。 /ordinary-atom
具体解释和示例见下,点击链接即可。
普通原子
magic nomagic 匹配
/^ ^ ^ 行首 (仅可用于模式开头) /zero-width
/\^ \^ \^ 按本义出现的 '^'
/\_^ \_^ \_^ 行首 (可用于任何位置) /zero-width
/$ $ $ 行尾 (仅可用于模式结尾) /zero-width
/\$ \$ \$ 按本义出现的 '$'
/\_$ \_$ \_$ 行尾 (可用于任何位置) /zero-width
/. . \. 任意单个字符,不含换行
/\_. \_. \_. 任意单个字符,包括换行
/\< \< \< 单词起始边界 /zero-width
/\> \> \> 单词结束边界 /zero-width
/\zs \zs \zs 设定匹配内容的起始位置 /zero-width
/\ze \ze \ze 设定匹配内容的结束位置 /zero-width
/\%^ \%^ \%^ 文件开头 /zero-width E71
/\%$ \%$ \%$ 文件末尾 /zero-width
/\%V \%V \%V 仅在可视选区内部 /zero-width
/\%# \%# \%# 光标位置 /zero-width
/\%'m \%'m \%'m 位置标记 m 所在位置 /zero-width
/\%l \%23l \%23l 第 23 行内 /zero-width
/\%c \%23c \%23c 第 23 列 /zero-width
/\%v \%23v \%23v 虚拟第 23 列 /zero-width
字符类: /character-classes
magic nomagic 匹配
/\i \i \i 标识符字符 (见 'isident' 选项)
/\I \I \I 类似 "\i",但不含数位字符
/\k \k \k 关键字字符 (见 'iskeyword' 选项)
/\K \K \K 类似 "\k",但不含数位字符
/\f \f \f 文件名字符 (见 'isfname' 选项)
/\F \F \F 类似 "\f",但不含数位字符
/\p \p \p 可显示字符 (见 'isprint' 选项)
/\P \P \P 类似 "\p",但不含数位字符
/\s \s \s 空白字符;<Space> 和 <Tab>
/\S \S \S 非空白字符: \s 之反
/\d \d \d 数位: [0-9]
/\D \D \D 非数位: [^0-9]
/\x \x \x 十六进制数位: [0-9A-Fa-f]
/\X \X \X 非十六进制数位: [^0-9A-Fa-f]
/\o \o \o 八进制数位: [0-7]
/\O \O \O 非八进制数位: [^0-7]
/\w \w \w 单词字符: [0-9A-Za-z_]
/\W \W \W 非单词字符: [^0-9A-Za-z_]
/\h \h \h 单词首字符: [A-Za-z_]
/\H \H \H 非单词首字符: [^A-Za-z_]
/\a \a \a 英文字母字符: [A-Za-z]
/\A \A \A 非英文字母字符: [^A-Za-z]
/\l \l \l 小写字母: [a-z]
/\L \L \L 非小写字母: [^a-z]
/\u \u \u 大写字母: [A-Z]
/\U \U \U 非大写字母 [^A-Z]
/\_ \_x \_x 其中 x 为以上任意字符类: 对应字符类加换行
(字符类结束)
magic nomagic 匹配
/\e \e \e <Esc>
/\t \t \t <Tab>
/\r \r \r <CR>
/\b \b \b <BS>
/\n \n \n 行尾结束符
/~ ~ \~ 最近替代字符串
/\1 \1 \1 第一个 \(\) 子表达式的匹配文本
/\2 \2 \2 第二个 \(\) 子表达式的匹配文本
...
/\9 \9 \9 第九个 \(\) 子表达式的匹配文本
E68
/\z1 \z1 \z1 仅用于语法高亮,见 :syn-ext-match
...
/\z1 \z9 \z9 仅用于语法高亮,见 :syn-ext-match
x x 普通无特殊含义的字符,匹配字符自身
/[] [] \[] 方括号内任意单个字符
/\%[] \%[] \%[] 可选原子序列,匹配尽量多个列出的原子
/\c \c \c 强制模式忽略大小写,不考虑 'ignorecase' 选项
/\C \C \C 强制模式区分大小写,不考虑 'ignorecase' 选项
/\Z \Z \Z 忽略模式内所有 Unicode 定义的组合字符差异,适用于希伯
来和阿拉伯带元音文本
magic nomagic 匹配
/\m \m \m 后续内容强制进入魔术模式 (相当于 'magic' 选项打开)
/\M \M \M 后续内容强制进入非魔术模式 (相当于 'magic' 选项关闭)
/\v \v \v 后续内容进入 "超魔术" 模式
/\V \V \V 后续内容进入 "超非魔术" 模式
/\%#= \%#=1 \%#=1 手动选择正则表达式引擎 /zero-width
/\%d \%d \%d 指定十进制编码的字符 (如 \%d123)
/\%x \%x \%x 指定十六进制编码的字符 (如 \%x2a)
/\%o \%o \%o 指定八进制编码的字符 (如 \%o040)
/\%u \%u \%u 指定 4 位十六进制编码的多字节字符 (如 \%u20ac)
/\%U \%U \%U 指定 8 位十六进制编码的超大多字节字符 (如 \%U12345678)
/\%C \%C \%C 任意数量的 Unicode 组合字符
示例 匹配
\<\I\i* 或
\<\h\w*
\<[a-zA-Z_][a-zA-Z0-9_]*
标识符 (适用于 C 语言)。
\(\.$\|\. \) 行尾英文句号、或英文句号后跟空格。
[.!?][])"']*\($\|[ ]\) 英文句子结尾。类似 ) 定义。
cat\Z "cat" 和 "càt" ("a" 后跟组合字符 0x0300)
不匹配 "càt" (字符 0x00e0),即使外观完全一致。
原子后面可以附加指示其匹配次数和匹配策略的修饰。这类修饰称为倍数项。总览可见
/multi 。
/star /\star
* 匹配前导原子 0 或多次,尽可能多地匹配 (贪婪)。
示例 'nomagic' 匹配
a* a\* ""、"a"、"aa"、"aaa" 等。
.* \.\* 不含换行的任意长度文本,包括空串
\_.* \_.\* 至缓冲区末尾所有内容
\_.*END \_.\*END 至缓冲区中最后一处 "END" (包含)
\*" 匹配按本义出现的 "*" 字符。非魔术模式下 "*" 和 "\*" 的功能互换。
特例: 当 "*" 出现在模式开头或紧跟在 "^" 之后时,只匹配星号字符自身。
要当心,"\_." 加多次倍数项会匹配大量文本,非常耗时。例如,"\_.*END" 会
匹配从当前位置到文件最后一处 "END"。因为 "*" 为贪婪匹配,会先一口气读
取文件末尾,再逐个字符回退,直到找到 "END" 为止。
/\+
\+ 匹配前导原子 1 次或多次。贪婪匹配。
例 匹配
^.\+$ 任意非空行
\s\+ 一个及以上空白字符
/\=
\= 匹配前导原子 0 或 1 次。贪婪匹配。
例 匹配
foo\= "fo"、"foo"
/\?
\? 同 \=。但不能用于反向搜索 ? 命令。
/\{ E60 E554 E870
\{n,m} 匹配前导原子 n 至 m 次。贪婪匹配
\{n} 严格匹配前导原子 n 次
\{n,} 匹配前导原子至少 n 次。贪婪匹配
\{,m} 匹配前导原子 0 至 m 次。贪婪匹配
\{} 匹配前导原子 0 或多次。贪婪匹配 (同 *)
/\{-
\{-n,m} 匹配前导原子 n 至 m 次。尽可能少地匹配 (非贪婪)
\{-n} 严格匹配前导原子 n 次
\{-n,} 匹配前导原子至少 n 次。非贪婪匹配
\{-,m} 匹配前导原子 0 至 m 次。非贪婪匹配
\{-} 匹配前导原子 0 或多次。非贪婪匹配
n 和 m 为正十进制数、或零
non-greedy
"-" 紧接在 "{" 后时,启用最短匹配优先 (非贪婪) 算法 (见下例)。特别地,
"\{-}" 类似 "*",但使用最短匹配优先算法。 不过 ,优先选择起始位置更早
的匹配,而非单纯最短,如 "a\{-}b" 会匹配 "xaaab" 中的 "aaab"。
示例 匹配
ab\{2,3}c "abbc"、"abbbc"
a\{5} "aaaaa"
ab\{2,}c "abbc"、"abbbc"、"abbbbc" 等
ab\{,3}c "ac"、"abc"、"abbc"、"abbbc"
a[bc]\{3}d "abbbd"、"abbcd"、"acbcd"、"acccd" 等
a\(bc\)\{1,2}d "abcd"、"abcbcd"
a[bc]\{-}[cd] 在 "abcd" 中匹配 "abc"
a[bc]*[cd] 在 "abcd" 中匹配 "abcd"
} 之前可加反斜杠转义,如: \{n,m\},但也可不加。
/\@=
\@= 正向先行断言,当前位置零宽度匹配前导原子。
类似 Perl 中的 "(?=pattern)"。
示例 匹配
foo\(bar\)\@= "foobar" 中的 "foo"
foo\(bar\)\@=foo 无法匹配
/zero-width
"\@=" (包括 "^","$","\<","\>" 等) 只做条件校验,不实际消耗字符,这
被称为零宽度项目。后续匹配仍从当前位置开始,这容易引起误解。如上面最后
一例不会匹配 "foobarfoo",因为 Vim 会尝试在匹配 "bar" 的同一位置再试图
匹配 "foo"。
注意 使用 "\&" 和 "\@=" 效果一致: 如 "foo\&.." 等价于 "\(foo\)\@=.."。
"\&" 写法更简洁,无需括号。
/\@!
\@! 负向先行断言。亦即,当前位置 不 匹配前导原子。 /zero-width
类似 Perl 中的 "(?!pattern)"。
示例 匹配
foo\(bar\)\@! 后面不跟 "bar" 的 "foo"
a.\{-}p\@! "a"、"ap"、"app"、"appp" 等。且后面不跟 "p"
if \(\(then\)\@!.\)*$ 后面不跟 "then" 的 "if "
使用 "\@!" 要小心,因为模式可以在很多位置不匹配。如 "a.*p\@!" 会从 "a"
开始匹配剩余整行内容,因为 ".*" 匹配完所有行内字符后,行尾自然不存在
"p"。而改写为非贪婪写法 "a.\{-}p\@!" 则可匹配 "a"、"ap"、"app" 等,只
要不再紧跟另外一个 "p" 就可以,这是因为 "." 可以匹配 "p" 而 "p\@!" 不
匹配其后内容 (译者注: 考虑 "apb",不匹配 "a",因为其后有 "p",匹配
"ap",因为其后没有 "b",不匹配 "apb",因为对于非贪婪匹配,"ap" 更短)。
不能用 "\@!" 断言在匹配位置之前不匹配其他内容。"\(foo\)\@!bar" 会匹配
"foobar" 中的 "bar",因为 "bar" 所在位置的内容并不匹配 "foo"。要匹配前
面不匹配 "foo" 的 "bar",可尝试 "\(foo\)\@!...bar",但有缺陷,不能匹配
位于行首的 "bar"。最好方法是负向回顾断言: "\(foo\)\@<!bar" (见下)。
实用范例: 要找到包含 "foo" 但不含 "bar" 的行:
/^\%(.*bar\)\@!.*\zsfoo
此模式先检查本行没有一个位置可以匹配 "bar"。否则 \@! 会导致本模式不匹
配。校验通过后,从行首开始寻找 "foo"。"\zs" 将匹配起点限定在 "foo" 本
身。
/\@<=
\@<= 正向回顾断言。紧贴在当前位置之前,零宽度匹配前导原子。 /zero-width
类似 Perl 的 "(?<=pattern)",但是 Vim 支持非固定宽度模式。
示例 匹配
\(an\_s\+\)\@<=file 在 "an" 后跟若干空白或换行之后紧接的 "file"。
为了提高性能,建议避免此倍数项,用 /\zs 替代。等价写法:
an\_s\+\zsfile
建议限定回溯字节,见下。
"\@<=" 和 "\@<!" 会检查在当前位置之前出现的匹配文本。理论上,匹配可从
当前位置之前的任意位置开始。为了限制回溯耗时,仅会在当前匹配行与上一行
(如有) 内回溯。这足以适配绝大多数场景,且时间可控。
在老式正则表达式引擎里,先匹配 "\@<=" 和 "\@<!" 之后的模式,所以不能在
其中用 "\1" 等子表达式引用前导原子内的 \(\)。反之却可行。
可用示例,但不推荐 匹配
\%#=1\1\@<=,\([a-z]\+\) "abc,abc" 中的 ",abc"
但新 NFA 正则表达式引擎工作方式不同,所以不建议依赖此行为,且尽量规避
\@<= 断言:
推荐示例 匹配
\([a-z]\+\)\zs,\1 "abc,abc" 中的 ",abc"
\@123<=
类似 "\@<=",但只回溯 123 个字节。大幅减少无效匹配,优化性能。例如,要
检查紧贴 "span" 之前是否有 "<":
/<\@1<=span
只检查 "span" 前一个字节,而这本来就是唯一可能匹配成功的位置。
回溯一旦跨过行边界,长度限制会改为从上一行的行尾算起,本行开头字符不计
入 (这只是为了处理简便)。
零相当于无限制。
/\@<!
\@<! 负向回顾断言。紧贴在当前位置之前 不 匹配前导原子。也就是,在当前行或上
一行中没有任何位置可匹配该原子,且匹配文本紧贴当前位置。 /zero-width
类似 Perl 的 "(?<!pattern)",但是 Vim 支持非固定宽度模式。
前导原子必须刚好终止在当前位置之前,因此可用 ".*" 结尾。
警告: 因为需要遍历众多可能位置,速度可能较慢,建议限定回溯字节,见下。
示例 匹配
\(foo\)\@<!bar 任何不在 "foobar" 中的 "bar"
\(\/\/.*\)\@<!in 不在 "//" 之后 (中间可有间隔) 的 "in"
\@123<!
类似 "\@<!",但只回溯 123 个字节。大幅减少无效匹配,优化性能。
/\@>
\@> 独占模式。匹配前导原子时要求完整匹配 (防止回溯)。
类似 Perl 的 "(?>pattern)"。
示例 匹配
\(a*\)\@>a 无法匹配 ("a*" 耗尽所有 "a",无法回溯以匹配之后的 "a")
试图作为完整模式匹配前导原子。一旦其后内容匹配失败,不会缩短前导原子的
匹配文本重试 (回溯),而直接停止匹配过程。
注意以下区别: "a*b" 和 "a*ab" 都匹配 "aaab",但后者里的 "a*" 只匹配前
两个 "a"。而 "\(a*\)\@>ab" 不会匹配 "aaab",因为 "a*" 会匹配 "aaa" (贪
婪匹配),导致 "ab" 无法匹配。
以下列出所有基本原子项:
/^
^ 出现在模式开头或 "\|"、"\("、"\%("、"\n" 之后: 匹配行首; /zero-width
在其它位置: 匹配按本义出现的 '^' 字符。
示例 匹配
^beep( C 函数 "beep" 的定义开头 (很可能)。
/\^
\^ 匹配按本义出现的 '^' 字符。可用于任何位置,[] 内部除外。
/\_^
\_^ 匹配行首。 /zero-width 可用于任何位置,[] 内部除外。
示例 匹配
\_s*\_^foo 任意数量空白及空白行,之后在行首出现 "foo"。
/$
$ 出现在模式末尾或 "\|"、"\)"、"\n" 之前: 匹配行尾 <EOL>; /zero-width
(译者注: 零宽度匹配,并不消耗换行)
在其它位置: 匹配按本义出现的 '$' 字符。
/\$
\$ 匹配按本义出现的 '$' 字符。可用于任何位置,[] 内部除外。
/\_$
\_$ 匹配行尾。 /zero-width 可用于任何位置,[] 内部除外。
注意: "a\_$b" 永远无法匹配,因为 "b" 不匹配换行。应改用 "a\nb" /\n 。
示例 匹配
foo\_$\_s* 出现在行尾 "foo",后接若干空白及空白行
. /. /\.
匹配任意单个字符,不包括换行。
"\." 匹配按本义出现的 "." 字符。非魔术模式下 "." 和 "\." 的功能互换。
/\_.
\_. 匹配任意单个字符,包括换行。
当心: "\_.*" 会一直匹配到缓冲区结尾的全部文本!
/\<
\< 匹配单词起始边界: 模式下一个字符是单词首字符。单词字符由 'iskeyword'
选项定义。 /zero-width
/\>
\> 匹配单词结束边界: 模式前一个字符是单词尾字符。单词字符由 'iskeyword'
选项定义。 /zero-width
/\zs
\zs 匹配任意位置,并在此处设置匹配起始位置,不能用于 [] 内部: 模式下一个字
符成为完整匹配的首个字符。 /zero-width
例如:
"^\s*\zsif"
匹配行首的 "if",忽略前置空白。
同一模式中可多次使用,实际生效的是匹配分支最后出现的位置。例如:
/\(.\{-}\zsFab\)\{3}
定位在第三次出现的 "Fab"。
其后不能有倍数项,否则报错。 E888
{仅当编译时加入 +syntax 特性才可用}
/\ze
\ze 匹配任意位置,并在此处设置匹配结束位置,不能用于 [] 内部: 模式前一个字
符成为完整匹配的最后一个字符。 /zero-width
同一模式中可多次使用,实际生效的是匹配分支最后出现的位置。例如:
/end\ze\(if\|for\)
可匹配 "endif" 和 "endfor" 中的 "end"。
其后不能有倍数项,否则报错。 E888
{仅当编译时加入 +syntax 特性才可用}
/\%^ start-of-file
\%^ 匹配文件开头。用于匹配字符串时,则匹配字符串起始位置。 /zero-width
例如,要搜索全文首个 "VIM":
/\%^\_.\{-}\zsVIM
/\%$ end-of-file
\%$ 匹配文件末尾。用于匹配字符串时,则匹配字符串结束位置。 /zero-width
注意 以下模式无法匹配全文最后一个 "VIM":
/VIM\_.\{-}\%$
只会找到下一处 VIM,因为后半段总会匹配。正确模式是:
/VIM\ze\(\(VIM\)\@!\_.\)*\%$
这里借助 /\@! 保证首个 "VIM" 之后 不再 出现 "VIM"。
更简单的方式是从文件末尾开始反向搜索!
/\%V
\%V 匹配可视选区内部。退出可视模式后,使用 gv 将会重新选中的区域。
零宽度 /zero-width 匹配。要确保整个模式完全落在可视选区内部,应在模
式开头与结尾都加上本原子。例如:
/\%Vfoo.*ba\%Vr
可视选区仅包含 "foo bar" 时,此模式也会生效。而:
/\%Vfoo.*bar\%V
仅当可视选择在 "r" 之后仍有内容时,此模式才会生效并匹配 "foo bar"。
仅对当前缓冲区生效。
/\%# cursor-position
\%# 匹配光标位置。仅在窗口中显示的缓冲区生效。 /zero-width
警告: 模式使用后如果光标移动,结果不再有效,但 Vim 并不立即自动刷新高
亮。语法高亮和 'hlsearch' 搜索高亮都会出现滞后。仅当切换或修改当前行
(刷新整行) 或执行 CTRL-L 命令 (刷新整屏) 时,才会更新高亮。
例如,要高亮光标所在单词:
/\k*\%#\k*
开启 'hlsearch' 时,移动光标并作若干更改,就能直观看到刷新发生的时间。
/\%'m /\%<'m /\%>'m
\%'m 匹配位置标记 m 所在位置。 /zero-width
\%<'m 匹配位置标记 m 之前位置。
\%>'m 匹配位置标记 m 之后位置。
例如,高亮位置标记 's 到 'e 之间 (包含) 的文本:
/.\%>'s.*\%<'e..
注意 末尾必须写两个句号才能包含位置标记 'e 所在字符。这是因为 "\%<'e"
匹配 'e 位置标记前一个字符,但作为零宽度匹配,本身不占用字符。
警 告: 模式使用后如果移动了位置标记,结果不再有效。但 Vim 并不立即自动
刷新高亮。这和 \%# 光标移动时的行为类似。
/\%l /\%>l /\%<l E951 E1204 E1273
\%23l 匹配指定行。 /zero-width
\%<23l 匹配指定行上方 (行号更小)。
\%>23l 匹配指定行下方 (行号更大)。
\%.l 匹配光标行。
\%<.l 匹配光标行上方。
\%>.l 匹配光标行下方。
以上六个原子匹配缓冲区内指定行。"23" 可被换为任意行号。首行行号为 1。
警告: 增删行时 Vim 不会立即自动刷新高亮。语法高亮会有滞后。使用 "." 引
用光标行时如果移动光标,也是如此 (译者注: 似不确,移到其他行时会自动更
新) 。仅当执行 CTRL-L 命令 (刷新整屏) 时,才会更新高亮。
例如,要高亮光标所在行:
:exe '/\%' .. line(".") .. 'l'
另一法是:
/\%.l
开启 'hlsearch' 时,移动光标并作若干更改,就能直观看到刷新发生的时间。
/\%c /\%>c /\%<c
\%23c 匹配指定列。 /zero-width
\%<23c 匹配指定列左侧。
\%>23c 匹配指定列右侧。
\%.c 匹配光标列。
\%<.c 匹配光标列左侧。
\%>.c 匹配光标列右侧。
以上六个原子匹配缓冲区或字符串内指定列。"23" 可被换为任意列号。首列列
号为 1。列号按字节计算,对多字节字符并不准确。
警告: 增删字符时 Vim 不会立即自动刷新高亮。语法高亮会有滞后。使用 "."
引用光标列时如果移动光标,也是如此。仅当执行 CTRL-L 命令 (刷新整屏)
时,才会更新高亮。
例如,要高亮光标所在列:
:exe '/\%' .. col(".") .. 'c'
另一法是:
/\%.c
开启 'hlsearch' 时,移动光标并作若干更改,就能直观看到刷新发生的时间。
匹配第 44 列单个字节的又一例:
/\%>43c.\%<46c
注意: "\%<46c" 匹配第 45 列,而 "." 匹配 44 列的一个字节。
/\%v /\%>v /\%<v
\%23v 匹配指定虚拟列。 /zero-width
\%<23v 匹配指定虚拟列左侧。
\%>23v 匹配指定虚拟列右侧。
\%.v 匹配光标所在虚拟列。
\%<.v 匹配光标所在虚拟列左侧。
\%>.v 匹配光标所在虚拟列右侧。
以上六个原子匹配缓冲区或字符串内指定虚拟列。在未被任何窗口显示的缓冲区
里匹配时,使用当前窗口的相关选项值 (如 'tabstop')。
"23" 可被换为任意列号。首列列号为 1。
注意 落在制表符或其他多宽字符的中间位置的虚拟列位置无法被选中。
警告: 增删字符时 Vim 不会立即自动刷新高亮。语法高亮会有滞后。使用 "."
引用光标列时如果移动光标,也是如此。仅当执行 CTRL-L 命令 (刷新整屏)
时,才会更新高亮。
例如,要高亮虚拟第 72 列右侧的所有字符:
/\%>72v.*
开启 'hlsearch' 时,移动光标并作若干更改,就能直观看到刷新发生的时间。
要匹配当前虚拟列 (光标所在位置) 右侧的所有字符:
/\%>.v.*
要匹配虚拟第 17 列 (不含) 左侧的所有文本:
/^.*\%17v
这里不包括第 17 列,因为这是零宽度 /zero-width 匹配。要包含该列:
/^.*\%17v.
等价写法,但即使第 17 列没有字符也能匹配:
/^.*\%<18v.
注意 如果没有 "^" 锚住首列,以下模式同样会高亮第 17 列:
/.*\%17v
'hlsearch' 之所以会高亮第 17 列,是因为存在另外一个位于第 17 列边界的
空匹配,其中 ".*" 匹配零个字符 (译者注: 该空匹配相当于 /\%17v ,后者
同样高亮第 17 列,这是因为空匹配仍然会在匹配位置高亮一个字符)。
字符类:
\i 标识符字符 (见 'isident' 选项) /\i
\I 类似 "\i",但不含数位字符 /\I
\k 关键字字符 (见 'iskeyword' 选项) /\k
\K 类似 "\k",但不含数位字符 /\K
\f 文件名字符 (见 'isfname' 选项) /\f
\F 类似 "\f",但不含数位字符 /\F
\p 可显示字符 (见 'isprint' 选项) /\p
\P 类似 "\p",但不含数位字符 /\P
备注: 以上字符类支持多字节字符,下面各项则仅匹配 ASCII 字符,因为其字符范围已
明确限定 (译者注: 不适用取反字符类,如 "\S"、"\D" 等,取反字符类会匹配所有非
ASCII 字符)。
whitespace white-space
\s 空白字符;<Space> 和 <Tab> /\s
\S 非空白字符: \s 之反 /\S
\d 数位: [0-9] /\d
\D 非数位: [^0-9] /\D
\x 十六进制数位: [0-9A-Fa-f] /\x
\X 非十六进制数位: [^0-9A-Fa-f] /\X
\o 八进制数位: [0-7] /\o
\O 非八进制数位: [^0-7] /\O
\w 单词字符: [0-9A-Za-z_] /\w
\W 非单词字符: [^0-9A-Za-z_] /\W
\h 单词首字符: [A-Za-z_] /\h
\H 非单词首字符: [^A-Za-z_] /\H
\a 英文字母字符: [A-Za-z] /\a
\A 非英文字母字符: [^A-Za-z] /\A
\l 小写字母: [a-z] /\l
\L 非小写字母: [^a-z] /\L
\u 大写字母: [A-Z] /\u
\U 非大写字母: [^A-Z] /\U
备注: 使用字符类原子,比使用 [] 构造执行速度要快。
备注: 字符类不受 'ignorecase'、"\c" 和 "\C" 设定影响。
/\_ E63 /\_i /\_I /\_k /\_K /\_f /\_F
/\_p /\_P /\_s /\_S /\_d /\_D /\_x /\_X
/\_o /\_O /\_w /\_W /\_h /\_H /\_a /\_A
/\_l /\_L /\_u /\_U
\_x "x" 为以上字符类可用字符之一: 匹配对应字符类、但也可匹配换行。
(字符类结束)
\e 匹配 <Esc> /\e
\t 匹配 <Tab> /\t
\r 匹配 <CR> /\r
\b 匹配 <BS> /\b
\n 匹配行尾结束符 (即换行) /\n
用于字符串而非缓冲区时,匹配按本义出现的换行符。
~ 匹配前次替代字符串 /~ /\~
"\~" 匹配按本义出现的 "~" 字符。非魔术模式下 "~" 和 "\~" 的功能互换。
\(\) 由转义括号括起的模式,称为子表达式 (捕获组) /\( /\(\) /\)
例如: "\(^a\)" 匹配行首的 'a'。
最多只能定义九个子表达式。如需更多分组,可用 \%( ,但不算作子表达式。
E51 E54 E55 E872 E873
\1 匹配第一个 \( 和 \) 间的子表达式匹配到的文本 /\1 E65
例如: "\([a-z]\).\1" 可匹配 "ata"、"ehe"、"tot" 等。
\2 类似 "\1",但使用第二子表达式, /\2
... /\3
\9 类似 "\1",但使用第九子表达式。 /\9
注意: 按模式中 "\(" 从左到右出现的先后顺序编号, 不 按匹配先后。
\%(\) 由转义的括号括起的模式 (非捕获组) /\%(\) /\%( E53
类似 \(\),但不算作子表达式,无法被引用。优点是可定义任意多组,且执行
速度稍快。
x 无特殊含义的普通字符,只匹配自身
/\ /\\
\x 单个反斜杠加普通字符,保留作后续版本扩展
[] /[] /\[] /\_[] /collection E76
\_[]
"\[" 匹配按本义出现的 "[" 字符。非魔术模式下 "[" 和 "\[" 的功能互换。
指定字符集合。匹配该集合里任意单个字符。
示例 匹配
[xyz] 'x'、'y' 或 'z' 之一
[a-zA-Z]$ 出现在行尾的字母字符
\c[a-z]$ 同上
[А-яЁё] 俄语字符集 (包括 utf-8 和 cp1251)
/[\n]
在 [] 前加上 "\_" 时,同时匹配换行,也可在集合内直接写入 "\n"。即使集
合以 "^" 开头,也不受影响!例如 "\_[^ab]" 会匹配换行以及除 "a"、"b" 以
外的所有字符。
此行为与 Vi 兼容: 除非使用 "\_" 形式或包含 "\n",否则集合不匹配换行。
E769
如果缺少 ']',Vim 不报错,而是判定此处不使用集合。方便直接搜索 '['。但
系统内部使用搜索模式时,仍会报错 E769。同时要注意在 :substitute 命令
里,这种情况会使整个命令被当作模式处理,例如 ":s/[/x/" 搜索 "[/x" 并替
代为空串,而不是搜索 "[" 并替代为 "x"!
E944 E945
集合以 "^" 开头时,规则改为匹配所有 不在 集合内的单个字符。如 "[^xyz]"
匹配 'x'、'y' 和 'z' 以外的所有字符。
- 以 '-' 隔开两个字符的字符区间,代表两者之间 (包含) 所有 ASCII 字符。
如 "[0-9]" 匹配所有十进制数位字符。如果起始字符大于结束字符,如
[c-a],会报错 E944。也可使用非 ASCII 字符,但老式正则表达式引擎不支
持两者编码差值超过 256。例如设置 re=1 后搜索 [\u3000-\u4000] 会报错
E945。在模式开头加上 \%#=2 强制启用新引擎可解决此问题。
- 字符类表达式,代表属于该字符类的字符集合。支持以下 POSIX 字符类:
名称 对应函数 匹配内容
[:alnum:] [:alnum:] isalnum ASCII 字母和数位字符
[:alpha:] [:alpha:] isalpha ASCII 字母
[:blank:] [:blank:] 空格和制表符
[:cntrl:] [:cntrl:] iscntrl ASCII 控制字符
[:digit:] [:digit:] 十进制数位字符 '0' 到 '9'
[:graph:] [:graph:] isgraph ASCII 可显示非空白字符
[:lower:] [:lower:] (1) 小写字母 (老式引擎 two-engines 在打
开 'ignorecase' 时匹配全部大小写字母)
[:print:] [:print:] (2) 可显示字符,包括空白
[:punct:] [:punct:] ispunct ASCII 标点字符
[:space:] [:space:] 空白字符: 空格、制表、CR、NL、垂直制
表、换页
[:upper:] [:upper:] (3) 大写字母 (老式引擎 two-engines 在打
开 'ignorecase' 时匹配全部大小写字母)
[:xdigit:] [:xdigit:] 十六进制数位字符: 0-9、a-f、A-F
[:return:] [:return:] <CR> 字符
[:tab:] [:tab:] <Tab> 字符
[:escape:] [:escape:] <Esc> 字符
[:backspace:] [:backspace:] <BS> 字符
[:ident:] [:ident:] 标识符字符 (同 "\i")
[:keyword:] [:keyword:] 关键字字符 (同 "\k")
[:fname:] [:fname:] 文件名字符 (同 "\f")
以下方括号括起的字符类表达式需加另一层方括号,作用是对方括号定界的字
符集合的扩充。例如,要匹配 UNIX 文件名: "[-./[:alnum:]_~]\+"。即一到
多个合法字符,合法字符包括 '-'、'.'、'/'、字母数位、'_' 或 '~'。
以上字符类仅对 8 位字符有效,但新正则表达式引擎也支持多字节字符的
[:lower:] 和 [:upper:] 类。见 two-engines 。将来,更多字符类可能会
支持多字节字符。目前,如需匹配所有 "alpha" 多字节字符,可用:
[[:lower:][:upper:]]。
"对应函数" 列展示实现调用的库函数,其具体实现取决于系统。特殊标注为:
(1) ASCII 字符调用 islower(),其他字符使用 Vim 内置规则
(2) 使用 Vim 内置规则
(3) 类似 (1),但使用 isupper() 而不是 islower()
/[[= [==]
- 等价类 (equivalence class),代表匹配和被比较字符语义相近的字符,例如
忽略重音符号的区别。目前支持 Unicode、latin1 和 latin9 编码。形式是:
[=a=]
/[[. [..]
- 排序元素 (collation element),目前仅支持单个字符:
[.a.]
(译者注: 部分语言支持多个字符作为单个排序元素,如西班牙语 "ch" 作为
单个字母,排在 "c" 和 "d" 之间,因此支持 [a-[.ch.]] 代表 "a"、"b"、
"c" 和 "ch",但 Vim 目前不支持多字符排序元素)。
/\]
- 要在集合内包含有特殊含义的字符 ']',^','-' 或 '\',可前置反斜杠,例
如: "[xyz\]]"、"[\^xyz]"、"[xy\-z]"、"[xyz\\]"。
(备注: POSIX 标准不支持这种反斜杠写法)。
']' 在集合开头时 (但可在 "^" 之后) 无须转义。例如: "[]xyz]"、
"[^] xyz]"。
'-' 在集合开头 (但可在 "^" 之后) 或结尾时无须转义。例如: "[-xyz]"、
"[^-xyz]"、"[xyz-]"。
'\' 在其后紧跟不属于 "^]-\bdertnoUux" 的字符时无须转义。例如:
"[\xyz]" 匹配 '\','x','y' 及 'z'。但推荐统一使用 "\\",防止后续版
本语法扩展造成歧义。
- 缺少末尾 ] 不会报错。"[]" 形式等同于 "[]]",仅匹配 ']' 字符。
- 当 'cpoptions' 中不包含 'l' 标志位时 ( cpo-l ),集合内支持下列转义:
\e <Esc>
\t <Tab>
\r <CR> ( 不同于 换行!)
\b <BS>
\n 换行,见上 /[\n]
\d123 十进制表示的字符
\o40 八进制表示的单字节字符,最大值为 0o377
\x20 十六进制表示的单字节字符,最大值为 0xff
\u20AC 十六进制表示的 2 字节字符,最大值为 0xffff
\U1234 十六进制表示的 4 字节字符,最大值为 0xffffffff E1541
备注: 前文所有其他反斜杠转义码 (译者注: 如 \s、\d 等) 在 [] 内无效!
- 字符集合匹配效率较低。因为需要逐个比对集合内每个字符。建议优先使用前
文提到的字符类原子。例如: "\d" 远快于 "[0-9]"。不过,新 NFA 正则引
擎对字符集合已做了优化,性能优于老式引擎。
/\%[] E69 E70 E369
\%[] 可选原子序列,总能匹配成功,会尽可能依次匹配括号内的原子,遇到第一个无
法匹配的项时停止。例如:
/r\%[ead]
匹配 "r"、"re"、"rea" 或 "read" 中最长的匹配项。下例匹配 Ex 命令
"function","fu" 必填,后续 "nction" 可选:
/\<fu\%[nction]\>
这里用到单词结束边界原子 "\>",避免匹配 "full" 中的 "fu"。
这里的原子未必是普通字符,虽然不常见,但可用更复杂构造。例如:
/\<r\%[[eo]ad]\>
匹配 "r"、"re"、"ro"、"rea"、"roa"、"read" 及 "road"。
[] 里不能包含 \(\) 、 \%(\) 或 \z(\) 构造,也不支持嵌套 "\%[]"。
要包含 "[" 字符,可用 "[[]";要包含 "]",则可用 "[]]",例如:
/index\%[[[]0[]]]
匹配 "index"、"index["、"index[0" 及 "index[0]"。
{仅当编译时加入 +syntax 特性才有效}
/\%d /\%x /\%o /\%u /\%U E678
\%d123 匹配十进制表示的字符。其后必须紧跟非数位字符。
\%o40 匹配八进制表示的字符,最大值为 0o377。小于 0o40 时,后面不能再跟八进制
数位字符 (即 0-7)。
\%x2a 匹配不超过两位十六进制数位表示的单字节字符。
\%u20AC 匹配不超过四位十六进制数位表示的 2 字节字符。
\%U1234abcd
匹配不超过八位十六进制数位表示的 4 字节字符,最大值为 0x7fffffff
(INT_MAX E1541 ,但合法 Unicode 代码点最大为 U+10FFFFF)。
开启 'ignorecase' 选项时,普通字母匹配忽略大小写。同时开启 'smartcase' 后,则
仅当模式只包含小写字母时,才忽略大小写。
/\c /\C
只要模式中任何位置出现 "\c",整个模式会像打开 'ignorecase' 一样,强制忽略大小
写。此时忽略 'ignorecase' 和 'smartcase' 设置。"\C" 则相反: 整个模式强制区分大
小写。
{仅 Vim 支持 \c 和 \C}
注意 'ignorecase',"\c" 和 "\C" 对字符类表达式无效。
相关选项组合示例:
模式 'ignorecase' 'smartcase' 能匹配
foo 关闭 - foo
foo 打开 - foo Foo FOO
Foo 打开 关闭 foo Foo FOO
Foo 打开 打开 Foo
\cfoo - - foo Foo FOO
foo\C - - foo
技术细节: NL-used-for-Nul
文件中的 <Nul> 字符在内存中被存为换行符 <NL>。显示为 "^@"。读写文件时自动完成
转换。要在搜索模式中匹配 <Nul>,可用 CTRL-@ 或 "CTRL-V 000",这符合用户逻辑。
实际上,搜索模式里的空字符在内部会被替换为 <NL>。较为特别的是,键入 CTRL-V
CTRL-J 也会插入 <NL>,因为在内部存储方式一致,同样可用来搜索文件里的 <Nul>
(译者注: Vim 内部不保存行尾结束符,会以其他方式分隔文本行,而 C 语言字符串又以
<Nul> 结尾,无法直接保存空字符,因此可将换行符用作空字符的内部表示)。
CR-used-for-NL
'fileformat' 为 "mac" 时,文件中的 <NL> 字符在内部被存为 <CR>。显示为 "^J"。其
余逻辑和 <NL> 用作 <Nul> 的用法类似。
表达式求值时,模式中的 <NL> 中字符则只匹配字符串中的 <NL>。用 "\n" (反斜杠 n)
匹配 <NL> 此处无效,它仅对匹配缓冲区文本有效 (译者注: 此处不确,见 /\n ,实测
可正确匹配)。
pattern-multi-byte pattern-multibyte
模式匹配可正常处理多字节字符。基本符合用户逻辑,不过要注意包含非法字节的模式几
乎无法匹配任何内容。
/\Z
只要模式中任何位置出现 "\Z",匹配时会忽略所有组合字符。只要求基本字符一致,文
本中的组合字符可以不同,数量也可任意。仅当 'encoding' 为 'utf-8' 时生效。
例外: 模式以一或多个组合字符开头时,这部分必须严格匹配。
/\%C
"\%C" 用来跳过任意数量的组合字符。例如,模式 "a" 不匹配 "càt" (这里 a 附加了组
合字符 0x0300),而模式 "a\%C" 则匹配。但注意该模式不匹配 "cát" (这里 á 字符编
码是 0xe1,不是 a 附加组合字符),但匹配 "cat" (普通 a 字符)。
组合字符出现在模式开头、或是紧跟不消耗组合字符的项之后时,会匹配任意包含该组合
字符的字符。
句号 ( /. ) 和组合字符联用时,效果相当于单独写组合字符,但不受前置字符限制。
组合字符之间不分先后顺序。另外,文本可比模式包含更多组合字符,不影响匹配。但模
式中列出的每个组合字符必须全数在文本中出现。
匹配示例,假定 B 是基本字符,x 和 y 是组合字符:
模式 文本 匹配与否
Bxy Bxy 是 (完全匹配)
Bxy Byx 是 (不分顺序)
Bxy By 否 (缺失 x)
Bxy Bx 否 (缺失 y)
Bx Bx 是 (完全匹配)
Bx By 否 (缺失 x)
Bx Bxy 是 (多余的 y 可被忽略)
Bx Byx 是 (多余的 y 可被忽略)
Vim 正则表达式和 Perl 功能上最为接近。差异主要体现在语法写法。对照汇总如下:
功能 Vim 方言 Perl 方言
强制忽略大小写 \c (?i)
强制区分大小写 \C (?-i)
非捕获组 \%(原子\) (?:原子)
非贪婪倍数项 \{-n,m} *?、+?、??、{}?
正向先行断言 原子\@= (?=原子)
负向先行断言 原子\@! (?!原子)
正向回顾断言 原子\@<= (?<=原子)
负向回顾断言 原子\@<! (?<!原子)
独占模式 (禁止回溯) 原子\@> (?>原子)
Vim 和 Perl 在匹配字符串中的换行符时,行为有所不同:
Perl 里,^ 和 $ 缺省只匹配整个文本的首尾。但可用 'm' 标志位使其匹配内嵌换行两
端。也可用 's' 标志位使句号 (.) 匹配换行 (顺便一提,Perl 可在模式内部通过上述
i 标志位类似写法,切换这些标志位)。
另一方面,Vim 中的 ^ 和 $ 永远匹配内嵌换行两端。但另有两个原子 \%^ 和 \%$ 匹配
(且仅匹配) 全文首尾。对第二个问题,Vim 用 \_ "修饰符" 来解决: 加在句号或字符类
前可使其同时匹配换行,如 /\_. 。
最后,以下构造是 Perl 独有的:
- 在正则表达式内执行任意代码: (?{perl 代码})
- 条件分支表达式: (?(条件)真值表达式|假值表达式)
… 而以下构造是 Vim 独有的:
- 切换模式的 'magic' 属性: \v \V \m \M (可大幅减少反斜杠转义)
- 可选原子序列: \%[atoms]
- \& (\& 之于 \| 就像 "与" 之于 "或";它要求多个分支在同一位置同时匹配)
- 按行号、列号匹配指定位置: \%5l \%5c \%5v
- 设置匹配区间起止: \zs \ze
syntax-vs-match
注意 匹配高亮机制和 syntax-highlighting 相互独立,后者一般是
缓冲区局部高亮,而匹配高亮局部于窗口,两者可以自由混用。match
系列高亮函数在场合和方式上灵活性更高,但多用于临时高亮,无需严
格规则。两种机制都可用来隐藏文本。
因此, matchadd() 这类匹配函数不会读取语法规则,同理,
synconcealed() 这类语法函数也不受匹配规则影响。
:mat :match
:mat[ch] {group} /{pattern}/
为当前窗口设置高亮模式,使用高亮组 {group}。例如:
:highlight MyGroup ctermbg=green guibg=green
:match MyGroup /TODO/
模式起止定界符 // 也可用任意其他字符替换。注意避开 '"' 和 '|'
等特殊字符。
执行命令时,{group} 高亮组必须已经预先定义。
同时会被 'hlsearch' 高亮的字符,仍然适用 {group} 高亮,因为匹
配高亮的优先级高于 'hlsearch'。而后者的优先级高于语法高亮 (见
'syntax')。
注意 高亮前次搜索模式的 'hlsearch' 对全局所有窗口生效。而通过
" match" 定义的模式仅对当前窗口生效。窗口切换缓冲区时会保留设
置。
模式不受 'ignorecase' 影响。但可在模式中使用 /\c 忽略大小
写,缺省区分大小写。
'redrawtime' 控制模式搜索的超时。
模式跨越多行而 Vim 仅重绘部分显示时,因为 Vim 只会从重绘起始行
开始搜索,容易造成高亮不完整等异常情况。
另见 matcharg() 和 getmatches() 。前者返回上次 :match 命
令使用的高亮组和模式。后者列出 matchadd() 和 :match 两者定
义的所有高亮组和模式。
:match 系列命令 ( :match 、 :2match 、 :3match ) 仅支持三种
模式。而 matchadd() 无此限制,且可额外指定匹配优先级。
高亮虚拟第 72 列及其右侧所有文本:
:highlight rightMargin term=bold ctermfg=blue guifg=blue
:match rightMargin /.\%>72v/
高亮位于虚拟第 7 列的文本:
:highlight col8 ctermbg=grey guibg=grey
:match col8 /\%<8v.\%>7v/
备注 用前后两个边界条件,确保制表符这类宽字符只要落在第 7 列就
会被完整高亮。
:mat[ch]
:mat[ch] none
清除上次定义的第一组高亮模式。
:2mat[ch] {group} /{pattern}/ :2match
:2mat[ch]
:2mat[ch] none
:3mat[ch] {group} /{pattern}/ :3match
:3mat[ch]
:3mat[ch] none
类似 :match ,但指定第二组和第三组模式。最多可用三组完全独立
的高亮模式。同一位置有多组模式同时命中时,编号越小优先级越高。
这里使用的匹配 ID 为 3。
":3match" 命令在 Vim 9.0.2054 版本之前用于 matchparen 插件。
建议手动规则采用 ":match",而其他插件可用 ":2match"。
matchadd() 系列函数提供了更灵活的替代方案。
模糊匹配要求候选文本包含模式里的所有字符且顺序一致,但字符不必连续,并按匹配程
度评判打分。
示例:
模式: "vim"
候选: "vim" -> 最优匹配
"vimeo" -> 好 (v i m)
"voice mail" -> 较弱 (v _ i _ _ _ m)
"vintage" -> 不匹配 (没有 "m")
搜索模式包含多个单词时,每个单词按以上规则独立匹配,且在候选中出现顺序不限。例
如,"get pat" 会匹配 "GetPattern"、"PatternGet"、"getPattern"、"patGetter"、
"getSomePattern"、"MatchpatternGet" 等。
模糊匹配不受 'ignorecase' 和 'smartcase' 选项影响,仅当模式只包含小写字母时,
才忽略大小写。
Vim 模糊匹配移植自 fzy 项目算法: https://github.com/jhawthorn/fzy
对指定模式和候选,采用动态规划计算最优匹配分数。
算法分为两个阶段:
1. 正向遍历
从左到右扫描候选,追踪每个模式位置的最佳分数。匹配出现在候选开头,单词开头
(空白、下划线、连字符、驼峰式大写字符 camelCase)、或直接紧跟上个匹配字符之
后可分别加分。
2. 反向遍历
从分数最高的结束位置开始逆向回溯,锁定整体最优的字符匹配位置。
Vim 在原版算法基本上,扩展支持多字节字符,能够正确匹配 UTF-8 和其他编码文本。
时间复杂度为 O(模式长度 * 候选长度)。内存开销也成相同比例。
函数 matchfuzzy() 和 matchfuzzypos() 对字符串列表执行模糊匹配。
matchfuzzy() 返回匹配字符串。而 matchfuzzypos() 在返回匹配项的同时也返回匹
配位置和分数。
:vimgrep 加上 "f" 标志位可开启模糊匹配。
要为 ins-completion 开启模糊匹配,可在 'completeopt' 选项里加入 "fuzzy" 值。
要为 cmdline-completion 开启,可在 'wildoptions' 选项里加入 "fuzzy" 值。
vim:tw=78:ts=8:noet:ft=help:norl: