pattern

pattern.txt 适用于 Vim 9.2 版本。 最近更新: 2026年2月 VIM 参考手册 by Bram Moolenaar 译者: lang2 正则模式与搜索命令 pattern-searches 基础知识请参考用户手册第 03.9 一节,更多说明可见第 27 章 usr_27.txt 。 1. 搜索命令 search-commands 2. 匹配模式的定义 search-pattern 3. 模式魔术性 /magic 4. 模式项总览 pattern-overview 5. 倍数项 pattern-multi-items 6. 基本原子项 pattern-atoms 7. 忽略模式大小写 /ignorecase 8. 组合字符匹配 patterns-composing 9. 对照 Perl 模式语法 perl-patterns 10. 匹配项高亮 match-highlight 11. 模糊匹配 fuzzy-matching

1. 搜索命令 search-commands

/ /{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"。 相当于接连执行两次搜索命令,不同之处在于: - 可用于操作符之后,整体作为单次动作。 - 后续 nN 命令的方向基于首条搜索。 - 任意一段匹配失败时,光标保持原位不动。 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 极罕见情况下,正则表达式会递归调用。例如,在执行长耗时模式匹配期间,在通道上检 查消息时,触发了使用模式搜索的回调或自动命令。多数此类场景可正常运行,但如果同 一正则模式被二次调用,会报错 (译者注: 内部模式对象包含状态,不可重用)。一般情 况下,此错误意味着所用模式有缺陷。

2. 匹配模式的定义 search-pattern pattern [pattern]

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。

3. 模式魔术性 /magic

字母等普通字符在模式中按本义出现时,只匹配自身。但在前面加上反斜杠时,这些字符 具备特殊含义。如 "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" 之前 * "*" 不出现在模式开头且不紧跟在 "^" 之后 )

4. 模式项总览 pattern-overview

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),即使外观完全一致。

5. 倍数项 pattern-multi-items

原子后面可以附加指示其匹配次数和匹配策略的修饰。这类修饰称为倍数项。总览可见 /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" 无法匹配。

6. 基本原子项 pattern-atoms

以下列出所有基本原子项: /^ ^ 出现在模式开头或 "\|"、"\("、"\%("、"\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)。

7. 忽略模式大小写 /ignorecase

开启 '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 模式匹配可正常处理多字节字符。基本符合用户逻辑,不过要注意包含非法字节的模式几 乎无法匹配任何内容。

8. 组合字符匹配 patterns-composing

/\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 可被忽略)

9. 对照 Perl 模式语法 perl-patterns

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

10. 高亮显示匹配 match-highlight

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() 系列函数提供了更灵活的替代方案。

11. 模糊匹配 fuzzy-matching

模糊匹配要求候选文本包含模式里的所有字符且顺序一致,但字符不必连续,并按匹配程 度评判打分。 示例: 模式: "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: