*pattern.txt* For Vim version 8.0. 最近更新: 2017年8月
VIM 参考手册 by Bram Moolenaar
译者: lang2 http://vimcdoc.sf.net
模式及查找命令 *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|
==============================================================================
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| {Vi: 无计数}
*N*
N 将上次的 "/" 或 "?" 在相反方向上重复 [count] 次。
|last-pattern| {Vi: 无计数}
*star* *E348* *E349*
* 正向查找第 [count] 次出现距离当前光标最近的单词的地
方。用于查找的单词是以下最先符合条件的:
1. 光标所在的关键字 |'iskeyword'|
2. 当前行内的光标后的第一个关键字。
3. 光标所在的非空白单词
4. 当前行内的光标后的第一个非空白单词
只查找整字,就像使用了命令 "/\<keyword\>" 一样。
(|exclusive| 开动作) {Vi 无此功能}
使用 'ignorecase',不使用 'smartcase'。
*#*
# 同 "*",但反向查找。也可以用磅符号 (字符 163)。如果
"#" 的功能和退格键一样,试着在启动 Vim 前使用
"stty erase <BS>" (<BS> 是 CTRL-H 或真的退格键)。
{Vi 无此功能}
*gstar*
g* 同 "*",但不使用 "\<" 和 "\>"。这样查找就会匹配非整字
的地方。{Vi 无此功能}
*g#*
g# 同 "#",但不使用 "\<" 和 "\>"。这样查找就会匹配非整字
的地方。{Vi 无此功能}
*gd*
gd 跳转 (goto) 至局部声明 (declaration)。当光标下是一个局
部变量时,此命令会跳转到该变量被声明的地方。
首先,Vim 会查找当前函数的起始处,就像使用 "[[" 一样。
如果找不到会停止在第一行。如果找到, Vim 会反向搜索直
到找到一个空行,然后从这里开始正向查找光标所在的关键
字,就像使用了 "*" 一样,但看起来象注释的行会被忽略。
(见 'comments' 选项)。
注意 这并非总有效。Vim 不会做语法分析。它仅仅查找关键
字的匹配。如果头文件也需要搜索的话,可以使用
|include-search| 列出的命令。
这个命令之后,可以使用 |n| 正向查找下一个匹配 (不能反
向)。
{Vi 无此功能}
*gD*
gD 跳转 (goto) 至全局声明 (Declaration)。当光标下是一个全
局变量时,此命令会跳转到该变量被声明的地方。此命令和
"gd" 命令一样,不过查找总是从第一行开始。{Vi 无此功能}
*1gd*
1gd 同 "gd",但忽略光标位置前结束的 {} 块里的匹配。
{Vi 无此功能}
*1gD*
1gD 同 "gD",但忽略光标位置前结束的 {} 块里的匹配。
{Vi 无此功能}
*CTRL-C*
CTRL-C 中止当前的 (搜索) 命令。在 MS-DOS 上用 CTRL-Break
|dos-CTRL-Break|。
在普通模式下,任何等待的命令将被终止。
*:noh* *:nohlsearch*
:noh[lsearch] 停止 'hlsearch' 选项的高亮显示。如果再执行查找命令或者
设定 'hlsearch' 选项,高亮会自动打开。此命令无法在自动
命令里使用,因为高亮的状态会在自动命令执行期间自动保存
和恢复 |autocmd-searchpat|。
执行用户函数时也是如此。
如果打开 'incsearch' 选项,键入查找模式时,即时显示当前的匹配。不过,你还得用
<CR> 来结束查找命令并将光标定位到显示的匹配。也可以用 <ESC> 来放弃查找。
如果打开 'hlsearch',最后一次查找命令的所有匹配点都会被高亮。用 |:nohlsearch|
命令来暂停。
如果没找到匹配,会报错: *E486* Pattern not found
注意 为 Vi 兼容起见,|:global| 命令会把此错误当作一个普通的消息。|:s| 命令的
"e" 标志位可用来避免此错误 |:s_flags|。
*search-offset* *{offset}*
这些命令查找一个指定的模式。而 "/" 和 "?" 命令还可以指定一个额外的偏移量。有两
种偏移: 行偏移和字符偏移。{Vi 没有字符偏移}
偏移用来指定光标相对于找到的匹配的位置:
[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" 前的第三个字符
如果把这些命令之一和一个操作符连用,影响的是查找之前和之后光标位置之间的字符。
然而,如果使用了行偏移,影响的是两光标位置之间的所有整行。
一个演示如何查找一个模式并用另一个单词来更改匹配的例子: >
<
*//;* *E386*
一个很特别的偏移是 ';' 后面接另一个查找命令。例如: >
其中第一例会先找到下一个出现 "test 1" 的地方,然后寻找在它之后 "test" 的第一次
出现之处。
这就好象接连执行两次查找命令,不同之处在于:
- 它可以被当作操作符之后的单个移动命令。
- 以后的 "n" 或 "N" 命令基于第一个查找操作。
- 当有错误时光标原地不动。
*last-pattern*
最近使用的模式和偏移会被记住。它们可以用来重复查找,而且查找的方向和计数都可以
修改。注意 Vim 会记住两个模式: 一个是普通模式下查找命令用的,另一个是替代命令
":s" 用的。每次给出一个空白的模式时,都将用到前次使用模式。不过,如果没有前次
搜索模式,如果可以,使用前次替代模式。
'magic' 选项的值是和最近使用模式本身绑定的。如果你改变了 'magic',最近使用模式
的解释方法不会改变。'ignorecase' 选项就不同。当 'ignorecase' 的值改变时,该模
式会匹配另外的文本。
如果你设定了 'hlsearch' 选项,所有最近使用的查找模式的匹配点都会高亮。
要清除最近使用的查找模式: >
这不会把该模式设置为空串,因为那样会匹配所有的东西。该模式是真的清除了,就象
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": >
另见 |/\%>l|。
另一个方法是使用 ":substitute" 命令并与 'c' 联用。例: >
这个命令会从光标所在处开始查找 "Pattern",直到第 300 行。在匹配处,你会被提示
键入一个字符。键入 'q' 终止;键入 'n' 找下一个匹配。
"*","#","g*" 和 "g#" 命令依照以下的次序查找在光标附近的一个单词,使用以下最
先找到的那个:
- 光标所在的关键字。
- 同行的光标右侧的第一个关键字。
- 光标下的第一个字串 (WORD)。
- 同行的光标右侧的第一个字串 (WORD)。
关键字只能包括字母和 'iskeyword' 中的字符。字串 (WORD) 可以包括任何非空白
(<Tab> 和/或 <Space>)。
备注 如果你用十个指头打字的话,这些字符是很容易记住的:
"#" 在你的左手中指上 (向左上查找);"*" 在你的右手中指上 (向右下查找)。
(不过,这取决于你的键盘布局)。
==============================================================================
2. 模式的定义 *search-pattern* *pattern* *[pattern]*
*regular-expression* *regexp* *Pattern*
*E76* *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 引擎,对某些模式会快很多,对某些模式可能会变慢。
Vim 会自动为你选择合适的引擎。不过,如果你遇过问题或者想特别指定某一个引擎,可
以在模式开头处加入:
\%#=0 强制自动选择。仅在 'regexpengine' 设为非零时才有效果。
\%#=1 强制使用旧引擎。
\%#=2 强制使用 NFA 引擎。
也可用 'regexpengine' 选项改变缺省机制。
*E864* *E868* *E874* *E875* *E876* *E877* *E878*
选择 NFA 引擎时如果遇到未实现的模式部分时,整个模式会不匹配。只用于调试 Vim。
==============================================================================
3. 魔术 */magic*
某些字符在模式中是按本义出现的。它们匹配自身。然而,当前面有一个反斜杠时,这些
字符具有特殊的含义。
另外一些字符即使没有反斜杠也代表特殊的意思。它们反而需要一个反斜杠来匹配按本义
出现的自身。
一个字符是否按本义出现取决于 'magic' 选项以及下面将解释的条目。
*/\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' 选项保持在缺省值 - '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| (*)
(*) {Vi 无此功能}
普通匹配原总览。 */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|
字符类 {Vi 无此功能}: */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 第一个 \(\) 匹配的字符 {Vi 无此功能}
|/\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"。
*/\+*
\+ 匹配一个或更多前面的匹配原。尽可能多。{Vi 无此功能}
例 匹配 ~
^.\+$ 任意空行
\s\+ 一个以上的空白字符
*/\=*
\= 匹配 0 或 1 个前面的匹配原。尽可能多。{Vi 无此功能}
例 匹配 ~
foo\= "fo" 和 "foo"
*/\?*
\? 和 \= 一样。不能和反向查找的 "?" 命令中使用。{Vi 无此功能}
*/\{* *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 个以上前面的匹配原。尽可能少
{Vi 没有这些}
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\}。
*/\@=*
\@= 零宽度匹配前面的匹配原。{Vi 无此功能}
类似于 Perl 中的 "(?=pattern)"。
示例 匹配 ~
foo\(bar\)\@= "foobar" 中的 "foo"
foo\(bar\)\@=foo 空
*/zero-width*
"\@=" (或 "^","$","\<","\>") 的匹配不包括任何字符。这些字符仅仅是用
来检查匹配是否存在。这很容易搞错,因为后续的项会在同样位置作匹配。上面
的最后一个例子不会匹配 "foobarfoo",因为 Vim 会尝试在 "bar" 匹配的同样
地方匹配 "foo"。
注意 使用 "\&" 同使用 "\@=" 是一样的: "foo\&.." 等于 "\(foo\)\@=.."。
但用 "\&" 容易些,你可以省了那些括号。
*/\@!*
\@! 零宽度否匹配,亦即,要求前面的匹配原在当前位置_不_匹配。
|/zero-width| {Vi 无此功能}
类似于 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"。如果 ".*bar" 匹配,\@!
会拒绝本模式。否则,继续寻找 "foo"。"\zs" 使得匹配从 "foo" 处开始。
*/\@<=*
\@<= 零宽度反向匹配。要求前面的匹配原紧贴在后面的模式之前匹配。
|/zero-width| {Vi 无此功能}
类似于 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| {Vi 无此功能}
类似于 Perl 的 "(?<!pattern)",但是 Vim 允许使用非固定宽度的模式。
该倍数所引用的匹配原必须紧贴在其后匹配之前,所以这个匹配原可以用 ".*"
结尾。警告: 该倍数项可能会很慢 (因为在匹配之前的许多位置都要被检查)。
如有可能,请使用限制范围,见下。
示例 匹配 ~
\(foo\)\@<!bar 任何不在 "foobar" 中的 "bar"
\(\/\/.*\)\@<!in 不在 "//" 之后 (中间可以有间隔) 的 "in"
\@123<!
类似于 "\@<!",但只往回看 123 个字节。这样可以避免去匹配很多已知不会成
功的但使模式很慢的尝试。
*/\@>*
\@> 匹配前面的匹配原时要求完整匹配 (不能回溯)。{Vi 无此功能}
类似于 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|
例如: >
< 匹配行首的 "if",忽略前导的空白字符。
可以使用多次,但实际使用最后一次在匹配的分支里遇到的。例如: >
< 找到第三次出现的 "Fab"。
不能后跟倍数。 *E888*
{Vi 无此功能} {仅当编译时加入 |+syntax| 特性才可用}
*/\ze*
\ze 匹配任何位置,并将匹配结尾处置于该处: 前一个字符将是整个匹配的最后一个
字符。|/zero-width|
可以使用多次,但实际使用最后一次在匹配的分支里遇到的。
例如: "end\ze\(if\|for\)" 匹配 "endif" 和 "endfor" 中的 "end"。
不能后跟倍数。 |E888|
{Vi 无此功能} {仅当编译时加入 |+syntax| 特性才可用}
*/\%^* *start-of-file*
\%^ 匹配文件头。当用于一个字符串时,匹配字符串起始处。{Vi 无此功能}
例如,要查找一个文件中首次出现 "VIM" 的地方: >
<
*/\%$* *end-of-file*
\%$ 匹配文件尾。当用于一个字符串时,匹配字符串结束处。{Vi 无此功能}
注意 下面的模式不匹配文件中的最后一个 "VIM": >
< 它会找到下一个 VIM,因为其后的部分总会匹配。这样才能匹配文件中的最后一
个 "VIM": >
< 这里使用了 |/\@!| 来确定在首个 "VIM" 之后_无法_再次匹配 "VIM"。
从文件尾部反向搜索会容易些!
*/\%V*
\%V 在可视区域内匹配。可视模式停止后,在 |gv| 将会重新选择的区域内匹配。
这是一个零宽度 |/zero-width| 匹配。要确保整个模式都在可视区域里,把本
匹配原放在匹配模式的开始和刚好结尾之前处,例如: >
< 这在可视选择只包含 "foo bar" 时,才会匹配。而: >
< 这在可视选择区在 "r" 之后继续时,才会匹配 "foo bar"。
只能用于当前缓冲区。
*/\%#* *cursor-position*
\%# 匹配光标位置。仅对显示于窗口内的缓冲区有效。{Vi 无此功能}
警 告: 如果使用了该模式之后光标被移动,结果不再有效,Vim 不会自动更新
匹配。这对语法高亮和 'hlsearch' 很重要。换言之: 在光标移动时显示并不因
此而更新。Vim 只对行被修改 (整行被更新) 或用户使用 |CTRL-L| 命令时 (整
个屏幕被更新) 进行更新。例如,要高亮显示光标下的单词: >
< 当设定 'hlsearch' 时,移动光标并作若干更改,你就能清楚地看到更新在何时
进行。
*/\%'m* */\%<'m* */\%>'m*
\%'m 匹配位置标记 m 的位置。
\%<'m 匹配位置标记 m 之前的位置。
\%>'m 匹配位置标记 m 之后的位置。
例如,高亮位置标记 's 到 'e 的文本: >
< 注意 在匹配里需要两个句号来包含位置标记 'e。这是因为 "\%<'e" 匹配 'e
位置标记之前的字符,而既然它是零宽度匹配 |/zero-width|,它并不真正包含
该字符。
{Vi 无此功能}
警 告: 如果使用模式后移动了位置标记,结果不再有效。Vim 并不自动更新匹
配。这和 "\%#" 里移动光标的情形类似 |/\%#|。
*/\%l* */\%>l* */\%<l*
\%23l 匹配指定的行。
\%<23l 匹配指定行的上方 (行号更小)。
\%>23l 匹配指定行的下方 (行号更大)。
这三个匹配原可以用来匹配缓冲区内的特定行。"23" 可以是任何行号。第一行
为 1。 {Vi 无此功能}
警 告: 当插入和删除行时 Vim 不会自动更新匹配。这意味着语法高亮很快就会
有问题。
例如,要高亮显示光标所在行: >
< 当设定 'hlsearch' 时,移动光标并作若干更改,你就能清楚地看到更新在何时
进行。
*/\%c* */\%>c* */\%<c*
\%23c 匹配指定的列。
\%<23c 匹配指定列之前。
\%>23c 匹配指定列之后。
这三个匹配原可以用来匹配缓冲区或字符串中的特定列。"23" 可以是任何列
号。第一列为 1。事实上,列以字节计算 (因此对多字节字符来说是不准确
的)。 {Vi 无此功能}
警 告: 当插入和删除字符时 Vim 并不自动更新匹配。这意味着语法高亮很快就
会有问题。
例如,要高亮显示光标所在列: >
< 当设定 'hlsearch' 时,移动光标并作若干更改,你就能清楚地看到更新在何时
进行。
一个匹配第 44 列单个字节的例子: >
< 注意: "\%<46c" 匹配第 45 列,而 "." 匹配 44 列的一个字节。
*/\%v* */\%>v* */\%<v*
\%23v 匹配指定虚拟列。
\%<23v 匹配指定虚拟列之前。
\%>23v 匹配指定虚拟列之后。
这三个匹配原可以用来匹配缓冲区或字符串中指定的虚拟列。如果不是在匹配窗
口内的缓冲区,使用当前窗口的选项值 (如 'tabstop')。
"23" 可以是任何列号。第一列为 1。
注意 某些虚拟列位置永远无法被匹配,因为它们在制表符或其它占用超过一个
屏幕位置的特殊字符的中间某处。{Vi 无此功能}
警 告: 当插入和删除字符时 Vim 并不自动更新高亮的匹配。这意味着语法高亮
很快就会有问题。
例如,要高亮显示所有位于虚拟第 72 列之后的字符: >
< 当设定 'hlsearch' 时,移动光标并作若干更改,你就能清楚地看到更新在何时
进行。
要匹配直到第 17 列的文本: >
< 这里不包括第 17 列,因为这是 |/zero-width| 匹配。要包含该列,应用: >
< 下例同上,但如果第 17 列没有字符也同样匹配: >
< 注意 如果没有 "^" 来锚住首列的匹配,第 17 列也能被高亮: >
< 'hlsearch' 高亮第 17 列,因为存在另外一个匹配,其中 ".*" 匹配零个字
符。
字符类: {Vi 无此功能}
\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*
相同的字符串。 {Vi 无此功能}
例如: "\([a-z]\).\1" 匹配 "ata","ehe","tot" 等。
\2 类似于 "\1",但使用第二子表达式, */\2*
... */\3*
\9 类似于 "\1",但使用第三子表达式。 */\9*
备注: 各组的标号是基于哪一个 "\(" 先出现 (自左至右),而_非_哪一个先匹
配。
\%(\) 一个由转义的括号括起来的模式。 */\%(\)* */\%(* *E53*
类似 \(\),但不算作一个子表达式。这样做允许使用更多的群组,并且处理时
会稍快些。
{Vi 无此功能}
x 一个没有特殊含义的单个字符,匹配其自身
*/\* */\\*
\x 一个反斜杠带一个没有特殊含义的单个字符,保留作将来的扩展
[] ('nomagic' 的情形: \[]) */[]* */\[]* */\_[]* */collection*
\_[]
一个集合。一组由方括号括起来的字符。匹配集合中的任何一个字符。
示例 匹配 ~
[xyz] 'x'、'y' 或 'z' 之一
[a-zA-Z]$ 出现在行尾的字母字符
\c[a-z]$ 同上
[Ð<90>-Ñ<8f>Ð<81>Ñ<91>] 俄语字符集 (包括 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> 字符
方括号括起的字符类表达式是对于方括号定界的集合的扩充。例如,下面的模
式是一个 UNIX 文件名: "[-./[:alnum:]_~]\+"。即至少有一个字符的字符列
表,其中字符可以是 '-','.','/',字母,数位,'_' 或 '~' 中的一个。
这些项仅对 8 位字符有效,但在新的正规表达式引擎里, [:lower:] 和
[:upper:] 也可用于多字节字符。见 |two-engines|。将来,其它项目可能也
可用于多字节字符。现在,要得到所有的 “alpha" 字符,可用:
[[:lower:][:upper:]]。
"函数" 列显示使用的库函数。具体实现取决于系统。否则:
(1) 编译时带 |+multi_byte| 特性时,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]" {Vi 无此功能}。
对于 '-' 你也可以将其作为第一个或最后一个字符: "[-xyz]","[^-xyz]"
或 "[xyz-]"。
对于 '\' 你也可以将其放置在除了 "^]-\bdertnoUux" 以外的任何一个字符
之前而无须转义: "[\xyz]" 匹配 '\','x','y' 及 'z'。但是用 "\\" 好
些,因为将来的扩展可能会在 '\' 之后使用其它字符。
- 省略结尾的 ] 不被视为错误。"[]" 等同于 "[]]",匹配 ']' 字符。
- 当 'cpoptions' 中不包括 'l' 标志位时,以下转义可用 {Vi 无此功能}:
\e <Esc>
\t <Tab>
\r <CR> (_不是_行尾符!)
\b <BS>
\n 换行符,见上 |/[\n]|
\d123 字符的十进制表示
\o40 字符的八进制表示,最大值为 0377
\x20 字符的十六进制表示,最大值为 0xff
\u20AC 多字节字符的十六进制表示,最大值为 0xffff
\U1234 多字节字符的十六进制表示,最大值为 0xffffffff
备注: 其它曾在前面提到的反斜杠转义码 (译者注: 如 \s、\d 等)
在方括号 [] 之内是不起作用的!
- 用集合来匹配可能会很慢。因为每个字符都要和集合中的每一个字符作比较。
尽可能使用上面提到的其它匹配原。例如: 同样是匹配一个数位,"\d" 要比
"[0-9]" 快的多。
*/\%[]* *E69* *E70* *E369*
\%[] 一个可选匹配原的序列。它总能匹配,但试图匹配尽量多的列出的匹配原,而在
第一个不匹配的地方终止。例如: >
< 匹配 "r","re","rea" 或者 "read"。采用最长可能的匹配。下面例子可以用
来匹配 Ex 命令 "function",其中 "fu" 是必须的而 "nction" 是可选的: >
< 这里用到了单词结尾匹配原 "\>" 来避免匹配 "full" 中的 "fu"。
当要匹配的不是普通字符时,问题就变得更复杂了。你不一定会经常这样,但可
以这么做。例如: >
< 匹配 "r","re","ro","rea","roa","read" 及 "road"。
[] 里不能有 \(\)、\%(\) 或 \z(\) 项,\%[] 也不能嵌套。
要包含 "[",用 "[[]" 而 "]" 则可用 "[]]",例如: >
< 匹配 "index"、"index["、"index[0" 和 "index[0]"。
{仅当编译时加入 |+syntax| 特性才有效}
*/\%d* */\%x* */\%o* */\%u* */\%U* *E678*
\%d123 匹配十进制指定的字符。后面必须跟着非数位。
\%o40 匹配八进制指定的字符,至多 0377。
小于 040 的数必须后面跟着非八进制的数位或非数位。
\%x2a 匹配不超过两位十六进制数位指定的字符。
\%u20AC 匹配不超过四位十六进制数位指定的字符。
\%U1234abcd 匹配不超过八位十六进制数位指定的字符。
==============================================================================
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>。{Vi 则完全不能处理文件中的 <Nul> 字符}
*CR-used-for-NL*
当 'fileformat' 为 "mac" 时,<NL> 字符在内部储存为 <CR>。在文本里显示为 "^J"。
除此以外,和 <NL> 作为 <Nul> 的用法类似。
在作表达式求值时,模式中的 <NL> 字符匹配字符串中的 <NL>。用 "\n" (反斜杠 n) 来
匹配 <NL> 在这里是行不通的,它仅对缓冲区内的文本有效。
*pattern-multi-byte*
模式匹配对于多字节字符同样适用。大体上使用并无区别,不过要注意无效字节可能引起
的问题,一个包含无效字节的模式永远不会得到匹配。
==============================================================================
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} 高亮。例: >
< 除了 // 以外,任何字符都可以用来标识一个 {pattern} 的开始和结
束。要当心某些特殊的字符,例如 '"' 和 '|'。
该命令执行时,{group} 必须已经定义。
对于 'hlsearch' 要高亮的字符,仍然适用 {group} 高亮,因为匹配
高亮的优先级比 'hlsearch' 要高。同样的,语法高亮 (见 'syntax')
也被匹配否决。
注意 使用 'hlsearch' 高亮显示最近使用的查找模式对所有窗口都有
效,而以 ":match" 定义的模式仅仅对当前窗口生效。当切换至另一个
缓冲区时,该设定被保留。
'ignorecase' 不起作用。在模式中使用 |/\c| 来忽略大小写,否则,
大小写总是区分的。
'redrawtime' 定义搜索模式匹配的最大时间。
匹配行尾而 Vim 只重绘部分显示时,结果可能会令你意想不到。这是
因为 Vim 在重绘开始的行上寻找匹配的缘故。
另见 |matcharg()| 和 |getmatches()|。前者返回上次 |:match| 命
令使用的高亮组和模式。后者返回 |matchadd()| 和 |:match| 两者定
义的所有高亮组和模式的列表。
|:match| 定义的高亮匹配仅限于三个 (除了 |:match| 以外,还有
|:2match| 和 |:3match| 可用)。而 |matchadd()| 无此限制,而且还
能排定匹配的优先级。
另一个例子,高亮显示虚拟第 72 列之后的所有文本: >
< 要高亮显示所有位于虚拟第 7 列的文本: >
< 注意 用两个项目是为了匹配那些占用了超过一个虚拟列的字符,例如
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" 用于其它的插件。