pattern

pattern.txt 适用于 Vim 9.0 版本。 最近更新: 2022年8月 VIM 参考手册 by Bram Moolenaar 译者: lang2 模式及查找命令 pattern-searches 最基本的东西可以在用户手册的 03.9 节中找到。在 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> 正向查找第 [count] 次出现 {pattern} 的地方 ( exclusive 开动作)。 /{pattern}/{offset}<CR> 正向查找第 [count] 次出现 {pattern} 的地方并向上或下移 动 {offset} 行。 linewise 行动作。 /<CR> /<CR> 正向查找第 [count] 次出现处,使用上次的模式 last-pattern 以及上次的 {offset} 。 //{offset}<CR> 正向查找第 [count] 次出现处,使用上次的模式 last-pattern 以及新偏移 {offset} 。若 {offset} 为 空,不使用任何偏移。 ? ?{pattern}[?]<CR> 反向查找第 [count] 次出现 {pattern} 的地方 ( exclusive 开动作) ?{pattern}?{offset}<CR> 反向查找第 [count] 次出现 {pattern} 的地方 并向上或下移动 {offset}linewise 行动作。 ?<CR> ?<CR> 反向查找第 [count] 次出现处,使用上次的模式 last-pattern 以及上次的 {offset} 。 ??{offset}<CR> 反向查找第 [count] 次出现处,使用上次的模式 last-pattern 以及新偏移 {offset} 。若 {offset} 为 空,不使用任何偏移。 n n 将上次的 "/" 或 "?" 重复 [count] 次。 如果光标不移动,搜索重复 count + 1 次。 last-pattern N N 将上次的 "/" 或 "?" 在相反方向上重复 [count] 次。 last-pattern 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)。当光标下是一个局 部变量时,此命令会跳转到该变量被声明的地方。 首先,Vim 会查找当前函数的起始处,就像使用 "[[" 一样。 如果找不到会停止在第一行。如果找到, 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 。 在普通模式下,任何等待的命令将被终止。 :noh :nohlsearch :noh[lsearch] 停止 'hlsearch' 选项的高亮显示。如果再执行查找命令或者 设定 'hlsearch' 选项,高亮会自动打开。此命令无法在自动 命令里使用,因为高亮的状态会在自动命令执行期间自动保存 和恢复 autocmd-searchpat 。 执行用户函数时也是如此。 如果打开 'incsearch' 选项,键入查找模式时,即时显示当前的匹配。不过,你还得用 <CR> 来结束查找命令并将光标定位到显示的匹配。也可以用 <ESC> 来放弃查找。 如果打开 'hlsearch',最后一次查找命令的所有匹配点都会被高亮。用 :nohlsearch 命令来暂停。 如果 'shortmess' 不包含 "S" 标志位,Vim 会自动显示光标所在的索引。看起来像这 样: [1/5] 光标在 5 个匹配的第一个。 [1/>99] 光标在多于 99 个匹配的第一个。 [>99/>99] 光标在多于 99 个匹配的第 99 个之后。 [?/??] 存在的匹配数未知,因为搜索超时,统计的生成被中断。 注意: 计数不考虑偏移。 如果没找到匹配,会报错: E486 Pattern not found 注意 为 Vi 兼容起见,老式脚本里, :global 命令会把此错误当作一个普通的消息 "Pattern not found"。 在 Vim9 脚本里,找不到模式里会报错 E486,而 :vglobal 如果模式匹配每一行, 会报 E538 :s 命令的 "e" 标志位可用来避免此错误 :s_flags search-offset {offset} 这些命令查找一个指定的模式。而 "/" 和 "?" 命令还可以指定一个额外的偏移量。有两 种偏移: 行偏移和字符偏移。 偏移用来指定光标相对于找到的匹配的位置: [num] [num] 行向下,第一列 +[num] [num] 行向下,第一列 -[num] [num] 行向上,第一列 e[+num] [num] 字符向右 (从匹配结束 (end) 处算起) e[-num] [num] 字符向左 (从匹配结束 (end) 处算起) s[+num] [num] 字符向右 (从匹配开始 (start) 处算起) s[-num] [num] 字符向左 (从匹配开始 (start) 处算起) b[+num] [num] 等价于 s[+num] (从匹配开始 (begin) 处算起) b[-num] [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 会记住两个模式: 一个是普通模式下查找命令用的,另一个是替代命令 ":s" 用的。每次给出一个空白的模式时,都将用到前次使用模式。不过,如果没有前次 搜索模式,如果可以,使用前次替代模式。 'magic' 选项的值是和最近使用模式本身绑定的。如果你改变了 'magic',最近使用模式 的解释方法不会改变。'ignorecase' 选项就不同。当 'ignorecase' 的值改变时,该模 式会匹配另外的文本。 如果你设定了 'hlsearch' 选项,所有最近使用的查找模式的匹配点都会高亮。 要清除最近使用的查找模式: :let @/ = "" 这不会把该模式设置为空串,因为那样会匹配所有的东西。该模式是真的清除了,就像 Vim 刚刚启动一样。 查找通常会跳过那些不移动光标位置的匹配。下一次匹配是开始于下一个字符还是在跳过 那些匹配之后取决于 'cpoptions' 选项中的 'c' 标志位。见 cpo-c 。 带 'c' 标志位: "/..." 前进 1 至 3 个字符 不带 'c' 标志位: "/..." 前进 1 个字符 带 'c' 标志位对应结果难以完全确定,因为查找可以从第一列开始,忽略任何匹配,直 到找到超过光标位置的匹配为止。 如果反向寻找,要是如上所述 'cpoptions' 里包含了 'c' 标志位的话,从行首开始搜 索,使用光标位置之前的最后一个匹配。 在 Vi 里 ":tag" 命令会将最近查找模式设定为要搜索的标签。除非 'cpoptions' 选项 中包括 't' 标志位,Vim 不会这样做,前次查找模式仍然被记住。查找模式总被存入查 找历史记录。 如果 'wrapscan' 选项的值为真 (缺省) 的话,查找会在缓冲区的结尾折返到首部。如果 不为真,反向查找会在开始处停止;正向查找会在结尾处停止。如果该选项为真但找不到 该模式,会给出一个错误信息: "pattern not found",光标原地不动。如果不为真,取 决于查找的方向是正向还是反向,给出的信息是: "search hit BOTTOM without match" 或者 "search hit TOP without match"。如果该选项为真,当查找折返时会分别显示: "search hit TOP, continuing at BOTTOM" 或 "search hit BOTTOM, continuing at TOP"。此时,消息可以用设定 'shortmess' 选项里的 's' 标志位来关闭。该信息的显示 会使用 'w' 的高亮方法 (缺省: 突出)。 search-range 用 \%>l 项目,你可以限定 "/" 命令查找的范围。例如,要在行 199 之下行 300 之上 搜索单词 "limit": /\%>199l\%<300llimit 另见 /\%>l 。 另一个方法是使用 ":substitute" 命令并与 'c' 联用。例: :.,300s/Pattern//gc 这个命令会从光标所在处开始查找 "Pattern",直到第 300 行。在匹配处,你会被提示 键入一个字符。键入 'q' 终止;键入 'n' 找下一个匹配。 "*","#","g*" 和 "g#" 命令依照以下的次序查找在光标附近的一个单词,使用以下最 先找到的那个: - 光标所在的关键字。 - 同行的光标右侧的第一个关键字。 - 光标下的第一个字串 (WORD)。 - 同行的光标右侧的第一个字串 (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. 一个分支是一个或多个被 "\&" 分隔的邻接。它匹配最后一个邻接,但仅仅当前面所 的邻接也在同样位置匹配。例: "foobeep\&..." 匹配 "foobeep" 中的 "foo"。 ".*Peter\&.*Bob" 匹配同时包括 "Peter" 和 "Bob" 的一行 branch ::= concat 或 concat \& concat 或 concat \& concat \& concat 等。 /concat 3. 一个邻接 (concat) 是一或多个相邻的组件 (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' 和 '_' 之外的字符都当 作特殊字符解释: "very magic" 使用 "\V" 会使得在它之后,只有反斜杠和终止字符 (通常是 / 或 ?) 有特殊的意 义: "very nomagic" 示例: 在这之后: \v \m \M \V 匹配 'magic' 'nomagic' a a a a 'a' (按本义) \a \a \a \a 字母字符 . . \. \. 匹配任何字符 \. \. . . 英文句号 (按本义) $ $ $ \$ 匹配行尾 * * \* \* 前面匹配原的任意次重复 ~ ~ \~ \~ 最近替代字符串 () \(\) \(\) \(\) 当作单个匹配原的组 | \| \| \| 空: 分隔可选分支 \\ \\ \\ \\ 反斜杠 (按本义) \{ { { { '{' (按本义) {仅 Vim 支持 \m,\M,\v 和 \V} 要使模式不受 'magic' 选项值的影响,在模式前面加上 "\m" 或 "\M"。

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 任何字符,设定匹配部分起始 /\ze \ze \ze 任何字符,设定匹配部分结束 /\%^ \%^ \%^ 文件首 /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 如 "\1",但用第二个 \(\) ... /\9 \9 \9 如 "\1",但用第九个 \(\) 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 对之后模式中字符设定 'magic' 选项为 "very magic" /\V \V \V 对之后模式中字符设定 'magic' 选项为 "very nomagic" /\%#= \%#=1 \%#=1 选择正则表达式引擎 /zero-width /\%d \%d \%d 匹配用十进制指定的字符 (如 \%d123) /\%x \%x \%x 匹配用十六进制指定的字符 (如 \%x2a) /\%o \%o \%o 匹配用八进制指定的字符 (如 \%o040) /\%u \%u \%u 匹配指定的多字节字符 (如 \%u20ac) /\%U \%U \%U 匹配指定的巨大多字节字符 (如 \%U12345678) /\%C \%C \%C 匹配任何组合字符 示例 匹配 \<\I\i* 或 \<\h\w* \<[a-zA-Z_][a-zA-Z0-9_]* 一个标识符 (例如,在一个 C 程序里)。 \(\.$\|\. \) 一个英文句号后跟 <EOL> 或一个空格。 [.!?][])"']*\($\|[ ]\) 一个匹配英文句子结尾的模式。几乎和 ")" 的定义相同。 cat\Z 匹配 "cat" 和 "càt" ("a" 后跟 0x0300) 不匹配 "càt" (字符 0x00e0),即使它们看起来可能一样。

5. 倍数项 pattern-multi-items

一个匹配原后面可以跟一个表示该匹配原匹配次数和方式的修饰。这个修饰称为倍数。 在 /multi 可以看到一个综述。 /star /\star * (在没有设定 'magic' 时使用 \*) 匹配 0 或更多个前面的匹配原,尽可能多地匹配。 示例 'nomagic' 匹配 a* a\* ""、"a"、"aa"、"aaa" 等。 .* \.\* 任意,包括空串,不包括行尾符 \_.* \_.\* 匹配至缓冲区结束 \_.*END \_.\*END 匹配至缓冲区中最后一次出现 "END" 处,包括该 "END" 特例: 当 "*" 用在模式的开头或者紧跟在 "^" 之后时,它匹配星号字符。 要当心,重复匹配 "\_." 会包括大量的文本,因而可能会花很长时间。例如, "\_.*END" 匹配从当前位置开始到文件中最后一次出现 "END" 的地方。因为 "*" 会尽可能多的匹配,它会先跳过到文件结束前的所有行,然后一次退一个字 符以查找 "END"。 /\+ \+ 匹配一个或更多前面的匹配原。尽可能多。 例 匹配 ^.\+$ 任意空行 \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\)\@!.\)*$ "if " 后面无跟随 "then" 使用 "\@!" 要小心,因为很多地方一个模式可以不匹配。"a.*p\@!" 会匹配一 个 "a" 直到行尾,因为 ".*" 匹配所有行内的字符,而 "p" 不在行尾匹配。 "a.\{-}p\@!" 则可以匹配 "a","ap","app" 等中的一项,只要它们不再紧跟 另外一个 "p",这是因为 "." 可以匹配 "p" 而 "p\@!" 不匹配这个 "p" 的后 面。 你不能用 "\@!" 去寻找匹配所在位置之前的否匹配。"\(foo\)\@!bar" 会匹配 "foobar" 中的 "bar",因为在 "bar" 匹配的位置上,"foo" 并不匹配。如果 不想匹配 "foobar",你可以尝试 "\(foo\)\@!...bar",但它不能匹配在行首出 现的 "bar"。最好的方法是用 "\(foo\)\@<!bar"。 有用的例子: 要找到包含 "foo" 但没有 "bar" 的行: /^\%(.*bar\)\@!.*\zsfoo 此模式先检查某行中没有一个位置可以匹配 "bar"。如果 ".*bar" 匹配,\@! 会拒绝本模式。否则,继续寻找 "foo"。"\zs" 使得匹配从 "foo" 处开始。 /\@<= \@<= 零宽度反向匹配。要求前面的匹配原紧贴在后面的模式之前匹配。 /zero-width 类似于 Perl 的 "(?<=pattern)",但是 Vim 允许使用非固定宽度的模式。 示例 匹配 \(an\_s\+\)\@<=file 在 "an" 和若干个空白或者行尾符之后的 "file"。 为了提高性能,最好避免这个倍数项。可以用 "\zs" 替代 /\zs 。要匹配 上述的示例: an\_s\+\zsfile 反向匹配时至少要设一个限制范围,见下。 "\@<=" 和 "\@<!" 检查刚好在其后模式匹配点之前出现的匹配文本。理论上, 这些匹配可以从当前位置之前的任何地方开始,为了限制所需的时间,只有其后 匹配所在的行和它上一行 (如果有上一行的话) 会被检索。这对大多数的应用来 说已经足够,而且也不会减慢速度太多。 在旧的正则表达式引擎里,在 "\@<=" 和 "\@<!" 之后的模式部分其实先被匹 配,所以不能用 "\1" 之类的结构来引用零宽度匹配原中的 \(\)。反过来倒是 可以的。 坏示例 匹配 \%#=1\1\@<=,\([a-z]\+\) "abc,abc" 里的 ",abc" 不过,新的正则表达式引擎工作方式不同,最好不要依赖此行为,如果可以避 免,不要用 \@<=: 示例 匹配 \([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*b" 和 "a*ab" 都匹配 "aaab",但是后者中的 "a*" 仅仅匹配前两个 "a"。"\(a*\)\@>ab" 不会匹配 "aaab",因为 "a*" 匹配了 "aaa" (尽可能多 的 "a"),导致 "ab" 无法匹配。

6. 普通匹配原 pattern-atoms

一个普通匹配原可能是: /^ ^ 在模式起点或在 "\|","\(","\%(","\n" 之后: 匹配行首;在其它位置匹配 按本义出现的 '^' 字符。 /zero-width 示例 匹配 ^beep( C 函数 "beep" 开始的地方 (很可能)。 /\^ \^ 匹配按本义出现的 '^' 字符。可以用于任何位置,不能用于 [] 内部。 /\_^ \_^ 匹配行首。 /zero-width 可以用于任何位置,不能用于 [] 内部。 示例 匹配 \_s*\_^foo 空白字符及空行,后接行首的 "foo"。 /$ $ 在模式终点或 "\|"、"\)" 或 "\n" (打开 'magic' 的话) 之前: 匹配行尾 <EOL>;其它位置,匹配按本义出现的 '$' 字符。 /zero-width /\$ \$ 匹配按本义出现的 '$' 字符。可以用于任何位置,不能用于 [] 内部。 /\_$ \_$ 匹配行尾。 /zero-width 可以用于任何位置,不能用于 [] 内部。注意: "a\_$b" 永远无法匹配,因为 "b" 不能匹配行尾符。可以使用 "a\nb" 代替 /\n 示例 匹配 foo\_$\_s* "foo" 在行尾,后接空白字符及空行 . ('nomagic' 的情形: \.) /. /\. 匹配任何单个字符,不包括行尾符。 /\_. \_. 匹配任何单个字符或行尾符。当心: "\_.*" 会一直匹配到缓冲区结尾! /\< \< 匹配单词起点: 下一个字符是单词的首字符。'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 \%^ 匹配文件头。当用于一个字符串时,匹配字符串起始处。 例如,要查找一个文件中首次出现 "VIM" 的地方: /\%^\_.\{-}\zsVIM /\%$ end-of-file \%$ 匹配文件尾。当用于一个字符串时,匹配字符串结束处。 注意 下面的模式不匹配文件中的最后一个 "VIM": /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 \%# 匹配光标位置。仅对显示于窗口内的缓冲区有效。 警 告: 如果使用了该模式之后光标被移动,结果不再有效,Vim 不会自动更新 匹配。这对语法高亮和 'hlsearch' 很重要。换言之: 在光标移动时显示并不因 此而更新。Vim 只对行被修改 (整行被更新) 或用户使用 CTRL-L 命令时 (整 个屏幕被更新) 进行更新。例如,要高亮显示光标下的单词: /\k*\%#\k* 当设定 'hlsearch' 时,移动光标并作若干更改,你就能清楚地看到更新在何时 进行。 /\%'m /\%<'m /\%>'m \%'m 匹配位置标记 m 的位置。 \%<'m 匹配位置标记 m 之前的位置。 \%>'m 匹配位置标记 m 之后的位置。 例如,高亮位置标记 's 到 'e 的文本: /.\%>'s.*\%<'e.. 注意 在匹配里需要两个句号来包含位置标记 'e。这是因为 "\%<'e" 匹配 'e 位置标记之前的字符,而既然它是零宽度匹配 /zero-width ,它并不真正包含 该字符。 警 告: 如果使用模式后移动了位置标记,结果不再有效。Vim 并不自动更新匹 配。这和 "\%#" 里移动光标的情形类似 /\%# /\%l /\%>l /\%<l E951 E1204 E1273 \%23l 匹配指定的行。 \%<23l 匹配指定行的上方 (行号更小)。 \%>23l 匹配指定行的下方 (行号更大)。 \%.l 匹配光标行。 \%<.l 匹配光标行的上方。 \%>.l 匹配光标行的下方。 这六个匹配原可以用来匹配缓冲区内的特定行。"23" 可以是任何行号。第一行 为 1。 警告: 当插入和删除行时 Vim 不会自动更新匹配。这意味着语法高亮很快就会 有问题。同样地引用光标位置 (".") 而移动光标时也是如此,显示不会自动随 移动更新。要更新可用 CTRL-L 命令 (全屏被刷新)。 例如,要高亮显示光标所在行: :exe '/\%' . line(".") . 'l' 另一法是: /\%.l 当设定 'hlsearch' 时,移动光标并作若干更改,你就能清楚地看到更新在何时 进行。 /\%c /\%>c /\%<c \%23c 匹配指定的列。 \%<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 匹配指定虚拟列。 \%<23v 匹配指定虚拟列之前。 \%>23v 匹配指定虚拟列之后。 \%.v 匹配光标所在虚拟列。 \%<.v 匹配光标所在虚拟列之前。 \%>.v 匹配光标所在虚拟列之后。 这六个匹配原可以用来匹配缓冲区或字符串中指定的虚拟列。如果不是在匹配窗 口内的缓冲区,使用当前窗口的选项值 (如 'tabstop')。 "23" 可以是任何列号。第一列为 1。 注意 某些虚拟列位置永远无法被匹配,因为它们在制表符或其它占用超过一个 屏幕位置的特殊字符的中间某处。 警告: 当插入和删除字符时 Vim 并不自动更新高亮的匹配。这意味着语法高亮 很快就会有问题。同样地引用光标位置 (".") 而移动光标时也是如此,显示不 会自动随移动更新。要更新可用 CTRL-L 命令 (全屏被刷新)。 例如,要高亮显示所有位于虚拟第 72 列之后的字符: /\%>72v.* 当设定 'hlsearch' 时,移动光标并作若干更改,你就能清楚地看到更新在何时 进行。 要匹配直到第 17 列的文本: /^.*\%17v 要匹配当前虚拟列 (光标所在位置) 之后的所有字符: /\%>.v.* 这里不包括第 17 列,因为这是 /zero-width 匹配。要包含该列,应用: /^.*\%17v. 下例同上,但如果第 17 列没有字符也同样匹配: /^.*\%<18v. 注意 如果没有 "^" 来锚住首列的匹配,第 17 列也能被高亮: /.*\%17v 'hlsearch' 高亮第 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 字符,因为它们由范围限定。 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 一个反斜杠带一个没有特殊含义的单个字符,保留作将来的扩展 [] ('nomagic' 的情形: \[]) /[] /\[] /\_[] /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 可以解决这个问题。 - 字符类表达式被解释为该字符类代表的字符集合。支持以下字符类: 名称 函数 内容 [:alnum:] [:alnum:] isalnum 字母和数位 [:alpha:] [:alpha:] isalpha 字母 [:blank:] [:blank:] 空格和制表 [:cntrl:] [:cntrl:] iscntrl 控制字符 [:digit:] [:digit:] 十进制数位 '0' 到 '9' [:graph:] [:graph:] isgraph ASCII 可显示字符,不包括空格 [:lower:] [:lower:] (1) 小写字母 (使用 'ignorecase' 时代表所有 字母) [:print:] [:print:] (2) 可显示字符,包括空格 [:punct:] [:punct:] ispunct ASCII 标点字符 [:space:] [:space:] 空白字符: 空格、制表、CR、NL、垂直制 表、换页 [:upper:] [:upper:] (3) 大写字母 (使用 '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() /[[= [==] - 等价类 (equivalence class)。匹配的字符和被比较的字符 "几乎" 相同,但 重音的区别可以忽略。目前支持 Unicode、latin1 和 latin9。形式是: [=a=] /[[. [..] - 排序规则元素 (collation element)。目前只能简单地接受如下形式的单个字 符: [.a.] /\] - 要在集合之内包括字符 ']',^','-' 或 '\',只需在该字符前加上反斜杠 "[xyz\]]","[\^xyz]","[xy\-z]" 和 "[xyz\\]"。 (备注: POSIX 不支持这种反斜杠的用法)。 对于 ']' 你也可以将其作为第一个字符 (但可能在 "^" 之后) 而无须转义: "[]xyz]" 或 "[^]xyz]"。 对于 '-' 你也可以将其作为第一个或最后一个字符: "[-xyz]","[^-xyz]" 或 "[xyz-]"。 对于 '\' 你也可以将其放置在除了 "^]-\bdertnoUux" 以外的任何一个字符 之前而无须转义: "[\xyz]" 匹配 '\','x','y' 及 'z'。但是用 "\\" 好 些,因为将来的扩展可能会在 '\' 之后使用其它字符。 - 省略结尾的 ] 不被视为错误。"[]" 等同于 "[]]",匹配 ']' 字符。 - 当 'cpoptions' 中不包括 'l' 标志位时,以下转义可用: \e <Esc> \t <Tab> \r <CR> ( 不是 行尾符!) \b <BS> \n 换行符,见上 /[\n] \d123 字符的十进制表示 \o40 字符的八进制表示,最大值为 0o377 \x20 字符的十六进制表示,最大值为 0xff \u20AC 多字节字符的十六进制表示,最大值为 0xffff \U1234 多字节字符的十六进制表示,最大值为 0xffffffff 备注: 其它曾在前面提到的反斜杠转义码 (译者注: 如 \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 的数必须后面跟着非八进制的数位或非数位。 \%x2a 匹配不超过两位十六进制数位指定的字符。 \%u20AC 匹配不超过四位十六进制数位指定的字符。 \%U1234abcd 匹配不超过八位十六进制数位指定的字符,直到 0x7fffffff

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> CR-used-for-NL 'fileformat' 为 "mac" 时,文件中的 <NL> 字符在内部储存为 <CR>。在文本里显示 为 "^J"。除此以外,和 <NL> 作为 <Nul> 的用法类似。 在作表达式求值时,模式中的 <NL> 字符匹配字符串中的 <NL>。用 "\n" (反斜杠 n) 来 匹配 <NL> 在这里行不通,它仅对匹配缓冲区内的文本有效。 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,没有组合字 符)。但匹配 "cat" (这里 a 就是简单的 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) 不须被引用的群组 \%(atom\) (?:atom) 保守的倍数描述 \{-n,m} *?,+?,??,{}? 零宽度匹配 atom\@= (?=atom) 零宽度否匹配 atom\@! (?!atom) 零宽度反向匹配 atom\@<= (?<=atom) 零宽度反向否匹配 atom\@<! (?<!atom) 无重试匹配 atom\@> (?>atom) (译注: 常见的其它译法 不须被引用的群组 非捕获分组 保守的倍数描述 非贪婪匹配 零宽度匹配 正向预搜索匹配 零宽度否匹配 正向预搜索不匹配 零宽度反向匹配 反向预搜索匹配 零宽度反向否匹配 反向预搜索不匹配 ) Vim 和 Perl 匹配一个字符串中的换行符时有所不同: 在 Perl 里,^ 和 $ 缺省只匹配文本的开始和结尾。但是你也可以设定 'm' 标志位来使 它们匹配内嵌的换行符。你还可以设定 's' 标志位使句号 (.) 可以也用来匹配换行符。 (顺便提一下,使用类似上面 i 标志位的用法,可以在在模式内部改变这两个标志位。) 另一方面,Vim 中的 ^ 和 $ 永远匹配内嵌的换行符。但另外有两个匹配原: \%^ 和 \%$,可以分别用来匹配 (且只匹配) 文本的起始和结尾。对第二个问题,Vim 用 \_ "修 饰符" 来解决: 把它放在一个句号或字符类之前,对应的模式就可以同时匹配换行字符。 最后,以下这些结构是 Perl 独有的: - 在正则表达式内执行任意代码: (?{perl 代码}) - 条件表达式: (?(条件)真值表达式|假值表达式) ... 而这些是 Vim 独有的: - 改变模式的 'magic' 属性: \v \V \m \M (对于避免反斜杠非常有用) - 可选匹配原的序列: \%[atoms] - \& (\& 之于 \| 就像 "与" 之于 "或";它强迫多个模式在同一个位置匹配) - 通过行/列号匹配: \%5l \%5c \%5v - 设置匹配的开始和结束位置: \zs \ze

10. 高亮显示匹配 match-highlight

:mat :match :mat[ch] {group} /{pattern}/ 定义一个在当前窗口高亮显示的模式。它会以 {group} 高亮。例: :highlight MyGroup ctermbg=green guibg=green :match MyGroup /TODO/ 除了 // 以外,任何字符都可以用来标识一个 {pattern} 的开始和结 束。要当心某些特殊的字符,例如 '"' 和 '|'。 该命令执行时,{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/ 注意 用两个项目是为了匹配那些占用了超过一个虚拟列的字符,例如 TAB。 :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 完全类似,但设置不同的匹配。这样,同时可以有 三组激活的匹配。如果不同匹配在相同位置出现,最小编号的匹配优 先。 ":3match" 命令用于 matchparen 插件。建议使用 ":match" 进行手 动的搜索,而 ":2match" 用于其它的插件。

11. 模糊匹配 fuzzy-matching

模糊匹配指使用非精确的搜索字符串匹配字符串的方法。模糊匹配会匹配某字符串,如果 搜索字符串的每个字符都出现在该字符串某个位置,且以相同顺序出现。忽略大小写。匹 配的字符串中,搜索字符串两个连续的字符之间可以有其它字符。如果搜索字符串有多个 单词,每个单词分别匹配。这意味着搜索字符串里这些单词可以在字符串中以任何顺序出 现。 模糊匹配为每个匹配的字符串按照以下标准打分: - 按顺序的匹配字符数目。 - 两个连续的匹配字符之间的字符数 (间隔)。 - 在某个单词开始处的匹配数目 - 从驼峰式大写字符 (例如 CamelCase 里的 Case) 开始的匹配数目 - 路径分隔符或连字符之后的匹配数目。 - 字符串中不匹配字符的数目。 优先返回最高分的匹配字符串。 例如,用模糊匹配来搜索 "get pat" 字符串,会匹配如下字符串 "GetPattern"、"PatternGet"、"getPattern"、"patGetter"、"getSomePattern"、 "MatchpatternGet" 等等。 函数 matchfuzzy()matchfuzzypos() 可用于在字符串列表中模糊匹配某个字符 串。matchfuzzy() 函数返回匹配字符串的列表。而 matchfuzzypos() 函数返回包含匹配、 匹配位置和模糊匹配分数的列表。 :vimgrep 的 "f" 标志位打开模糊匹配。 vim:tw=78:ts=8:noet:ft=help:norl: