*pattern.txt* For Vim version 6.4. 最近更新:2006年3月
VIM REFERENCE MANUAL 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. 与 Perl 匹配模式的比较 |perl-patterns|
9. 高亮显示匹配 |match-highlight|
1. 查找命令 *search-commands* *E486*
*/* /{pattern}
[/]<CR>
向前查找第[count]
次出现{pattern}
的地方 (不包含 |exclusive|) /{pattern}
/{offset}
<CR>
向前查找第[count]
次出现{pattern}
的地方 并向上或下移动 |{offset}">{offset}
| 行 |linewise|。 */<CR>* /<CR>
向前查找第[count]
次出现处,使用上次的模式 |last-pattern| 以及 |{offset}">{offset}
|。 //{offset}
<CR>
向前查找第[count]
次出现处,使用上次的模式 |last-pattern| 以及新偏移 |{offset}">{offset}
|. 若{offset}
为空不使用任何偏移。 *?* ?{pattern}
[?]<CR>
向后查找第[count]
次出现{pattern}
的地方 (不包含 |exclusive|) ?{pattern}
?{offset}
<CR>
向后查找第[count]
次出现{pattern}
的地方 并向上或下移动 |{offset}">{offset}
| 行 |linewise|。 *?<CR>* ?<CR>
向后查找第[count]
次出现处,使用上次的模式 |last-pattern| 以及 |{offset}">{offset}
|。 ??{offset}
<CR>
向后查找第[count]
次出现处,使用上次的模式 |last-pattern| 以及新偏移 |{offset}">{offset}
|. 若{offset}
为空不使用任何偏移。 *n* n 将上次的 "/" 或 "?" 重复[count]
次。 |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 跳转至局部声明。当光标下是一个局部变量时,此命令会跳转 到该变量被声明的地方。首先,Vim 会查找当前函数的起始处。 就象使用 "[[" 一样。如果找不到会停止在第一行。如果找到, Vim 会向后直到找到一个空行,然后从这里开始向前查找光标 下的关键字,就象 "*"。看起来象注释的行会被忽略。 (见 'comments' 选项).注意
这并非总有效。Vim 不会做语法分析。它仅仅查找关键 字的匹配。如果需要搜索头文件的话,可以使用 |include-search| 列出的命令。 这个命令之后,可以使用 |n| 向前查找下一个匹配 (不能向 后)。{Vi 无此功能}
*gD* gD 跳转至全局声明。当光标下是一个全局变量时,此命令会跳转 到该变量被声明的地方。这和 "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| 命令终止。 *search-offset* *{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) 处算起) 如果给出了 '-' 或 '+' 但是省略了[num]
,会使用缺省的 1。如果使用了 'e' 偏移, 查找会成为包含的 (光标要到达的字符本身被包含在操作里)。 示例:模式 光标位置
/test/+1 "test" 下一行,第一列 /test/e "test" 的后一个 't' /test/s+2 "test" 中的 's' /test/b-3 "test" 前的第三个字符 如果把这些命令之一和一个操作符连用,查找之前和之后光标位置之间的字符会被影响。 然而,如果一个行偏移被使用,两光标位置之间的所有行都被影响。 一个如何查找一个模式并用另一个单词来更改匹配的例子:/foo
<CR>
查找 "foo"c//e 改变从当前位置到匹配结尾的部分
bar
<Esc>
输入要改变的内容//
<CR>
跳转到下一个相同匹配的开始c//e 改变从当前位置到匹配结尾的部分
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' 标志的不可预见性。 在 Vi 里 ":tag" 命令会将最后一次查找的模式设定为要搜索的标签。Vim 没有这样做。 前一次查找的模式仍然被记住,除非 'cpoptions' 选项中包括 't' 标志位。查找模式 总被存入查找历史记录。 如果 '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* 你可以限定 "/" 命令查找的范围。一个窍门是使用 ":substitute" 命令并与 'c' 联用。 例::.,300s/Pattern//gc
这个命令会从光标所在处开始查找 "Pattern",直到第 300 行。在匹配处,你会被提示 键入一个字符。键入 'q' 终止;键入 'n' 找下一个匹配。 "*","#","g*" 和 "g#" 命令依照以下的次序在光标附近查找一个单词,第一个被找到的 会被使用: - 光标下的关键字。 - 同行的光标右侧的第一各关键字。 - 光标下的第一个字 (WORD)。 - 同行的光标右侧的第一个字 (WORD)。 关键字只能包括字母和 'iskeyword' 中的字符。字 (WORD) 可以包括任何非空白 (<Tab>
和/或<Space>
) 。注意
如果你用十个指头打字的话,这些字符是很容易记住的: "#" 在你的左手中指上 (向左上查找);"*" 在你的右手中指上 (向右下查找)。 (这取决于你的键盘布局).
2. 模式的定义 *search-pattern* *pattern* *[pattern]*
*regular-expression* *regexp* *Pattern* *E76* *E361* *E363* *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(|
4. 模式项总览 *pattern-overview*
倍数总览。 */multi* *E61* *E62* 下面给出一些解释和示例,包括链接。 *E64*倍数
'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| |/\%#| \%# \%# 光标位置 |/zero-width| |/\%l| \%23l \%23l 在第 23 行 |/zero-width| |/\%c| \%23c \%23c 在第 23 列 |/zero-width| |/\%v| \%23v \%23v 在虚拟第 23 列 |/zero-width| 字符类{Vi 无此功能}
: |/\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 可以是以上任意一个字符:包括行尾的字符类 (字符类结束) |/\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 忽略大小写 |/\C| \C \C 匹配大小写 |/\m| \m \m 对之后模式中字符打开 'magic' 选项 |/\M| \M \M 对之后模式中字符关闭 'magic' 选项 |/\v| \v \v 对之后模式中字符设定 'magic' 选项为 "very magic" |/\V| \V \V 对之后模式中字符设定 'magic' 选项为 "very nomagic" |/\Z| \Z \Z 忽略 Unicode 中的 "组合用字符",对于搜索带元音的希伯来 和阿拉伯文本有用。示例 匹配
\<\I\i* 或 \<\h\w* \<[a-zA-Z_][a-zA-Z0-9_]* 一个标识符 (例如,在一个 C 程序里)。 \(\.$\|\. \) 一个英文句号后跟<EOL>
或一个空格。 [.!?][])"']*\($\|[ ]\) 一个匹配英文句子结尾的模式。类似于 ")" 的定义。 cat\Z 匹配 "cat" 和 "càt" ("a" 后跟 0x0300) 不匹配 "càt" (字符 0x00e0),即使它们看起来可能一样。
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' $ $ $ \$ 匹配行尾 . . \. \. 匹配任何字符 * * \* \* 前面匹配原的任意次重复 () \(\) \(\) \(\) 组成为单个匹配原 | \| \| \| 分割 alternatives \a \a \a \a 字母字符 \\ \\ \\ \\ 反斜杠 (按本义) \. \. . . 英文句号 (按本义) \{ { { { '{' (按本义) a a a a 'a' (按本义){only 只有 Vim 支持 \m,\M,\v 和 \V}
建议始终将 'magic' 选项保持在缺省值 - 'magic'。这可以避免移植性的麻烦。要使 模式不受该选项值的影响,在模式前面加上 "\m" 或 "\M"。
5. 倍数项 *pattern-multi-items*
一个匹配原后面可以跟一个表示该匹配原匹配次数和方式的修饰。这个修饰被称为倍数。 在 |/multi| 可以看到一个综述。 如果一个匹配原可以匹配空串,其后就不能使用倍数。那样可能会引起死循环。如果你坚 持要试,你会得到一个错误信息:*, \+ or \{ operand could be empty
*/star* */\star* *E56* * (在没有设定 'magic' 使用 \*) 匹配 0 或更多个前面的匹配原,尽可能多地匹配。示例 'nomagic' 匹配
a* a\* "","a","aa","aaa" 等。 .* \.\* 任意,包括空串,不包括行尾 \_.* \_.\* 匹配至缓冲结束 \_.*END \_.\*END 匹配至缓冲中最后一次出现 "END" 处,包括该 "END" 特例: 当 "*" 被使用在模式的开头或者紧跟在 "^" 之后时它匹配星号字符。 要当心,重复匹配 "\_." 会包括大量的文本,因而可能会花很长时间。例如, "\_.*END" 匹配从当前位置开始到文件中最后一次出现 "END" 的地方。因为 "*" 会尽可能多的匹配,这会先跳过到文件结束前的所有行然后反方向逐字查找 "END"。 */\+* *E57* \+ 匹配一个或更多前面的匹配原。尽可能多。{Vi 无此功能}
例 匹配
^.\+$ 任意空行 \s\+ 一个以上的空白字符 */\=* \= 匹配 0 或 1 个前面的匹配原。尽可能多。{Vi 无此功能}
例 匹配
foo\= "fo" 和 "foo" */\?* \? 和 \= 一样。不能和 "?" 命令中使用。{Vi 无此功能}
*/\{* *E58* *E60* *E554* \{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 是正的十进制数 如果一个 "-" 紧接在 "{" 之后,那么最短匹配优先算法将被启用 (见下面的例 子)。特别的,"\{-}
" 和 "*" 一样,只不过使用了最短匹配优先算法。_但_, 一个更早开始的匹配比一个更短的匹配优先: "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" 等。后面不带 "p" if \(\(then\)\@!.\)*$ "if " 后面无跟随 "then" 使用 "\@!" 要小心,因为很多地方一个模式可以不匹配。"a.*p\@!" 会匹配 一个 "a" 直到行尾,因为 ".*" 匹配所有行内的字符,而 "p" 不匹配行尾。 "a.\{-}
p\@!" 则可以匹配 "a","ap","aap" 等中的一项,只要它们不再紧跟 另外一个 "p",这是因为 "." 可以匹配 "p" 而 "p\@!" 不匹配这个 "p" 的后 面。 你不能用 "\@!" 去寻找匹配所在位置之前的否匹配。"\(foo\)\@!bar" 会匹配 "foobar" 中的 "bar",因为在 "bar" 匹配的位置上,"foo" 并不匹配。如果 不想匹配 "foobar",你可以尝试 "\(foo\)\@!...bar",但它不能匹配在行首出 现的 "bar"。最好的方法是用 "\(foo\)\@<!bar"。 */\@<=* \@<= 零宽度匹配,如果前面的匹配原所匹配的文本出现在其后的匹配的文本之前。{Vi 无此功能}
和 Perl 的 '(?<=pattern)" 类似,但是 Vim 允许使用非固定宽度的模式。示例 匹配
\(an\_s\+\)\@<=file 在 "an" 和若干个空白或者回车之后的 "file"。 为了提高性能,最好避免这个倍数项。可以用 "\zs" 替代 |/\zs|。要匹配 上述的示例:an\_s\+\zsfile
"\@<=" 和 "\@<!" 检查刚好在其后匹配之前出现的匹配文本。理论上,这些匹 配可以从当前位置之前的任何地方开始,为了限制所需的时间,只有其后匹配所 在的行和它上一行 (如果有上一行的话) 会被检索。这对大多数的应用来说已经 足够,而且也不会减慢速度太多。 在 "\@<=" 和 "\@<!" 之后的模式其实先被匹配,所以 "\1" 之类的结构不能用 来引用这两个倍数所引用的匹配原中的 \(\)。反过来倒是可以的。
示例 匹配
\1\@<=,\([a-z]\+\) ",abc" in "abc,abc" */\@<!* \@<! 零宽度匹配,如果前面的匹配原所匹配的文本_不_出现在其后的匹配的文本之 前。换而言之,如果在当前或者前一行中没有任何位置这个匹配原可以匹配而且 它匹配文本刚好紧贴在其后匹配之前。|/zero-width|{Vi 无此功能}
和 Perl 的 '(?<!pattern)" 类似,但是 Vim 允许使用非固定宽度的模式。 该倍数所引用的匹配原必须紧贴在其后匹配之前,所以这个匹配原可以用 ".*“ 结尾。警告:该倍数项可能会很慢 (因为在匹配之前的许多位置都要被检查)。示例 匹配
\(foo\)\@<!bar 任何不在 "foobar" 中的 "bar" \(\/\/.*\)\@\<!in 不在 "//" 之后 (中间可以有间隔) 的 "in" */\@>* \@> 匹配前面的匹配原时要求完整匹配 (不能回溯)。{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"。 */$* $ 在模式终点或 "\|","\)" ("\v" 之后的 "|",")" ) 之前: 匹配行尾<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",忽略所有空白字符。 可以使用多次,但实际使用最后一次在匹配的分支里遇到的。例如:/\(.\
找到第三次出现的 "Fab"。{-}
\zsFab\)\{3}
{Vi 无此功能}
{only 只有在编译时加入 +syntax 特性才可用}
*/\ze* \ze 匹配任何位置,并将匹配结尾处置于该处: 前一个字符将是整个匹配的最后一个 字符。|/zero-width| 可以被多次使用,最后一个分支中的将被选中。 例如: "end\ze\(if\|for\)" 匹配 "endif" 和 "endfor" 中的 "end"。{Vi 无此功能}
{only 只有在编译时加入 +syntax 特性才可用}
*/\%^* *start-of-file* \%^ 匹配文件头。当用于一个字符串时,匹配字符串起始处。{Vi 无此功能}
例如,要查找一个文件中首次出现 "VIM" 的地方:/\%^\_.\
*/\%$* *end-of-file* \%$ 匹配文件尾。当用于一个字符串时,匹配字符串结束处。{-}
\zsVIM{Vi 无此功能}
注意
下面的模式不匹配文件中的最后一个 "VIM":/VIM\_.\
它会找到下一个 VIM,因为其后的部分总会匹配。这个才能匹配文件 中的最后一个 "VIM":{-}
\%$/VIM\ze\(\(VIM\)\@!\_.\)*\%$
这使用了 |/\@!| 来确定在第一 "VIM" 之后无法再次匹配 "VIM"。 从文件尾部向前搜索会容易些! */\%#* *cursor-position* \%# 匹配光标位置。仅对显示于窗口内的缓冲有效。{Vi 无此功能}
警 告: 如果使用了该模式之后光标被移动,结果会成为无效的。Vim 不会自动的 更新匹配。这对语法高亮和 'hlsearch' 有更大的关系。换言之: 在光标移动时 显示并不因此而更新。Vim 只更新改动的行 (整行被更新) 或用户使用 |CTRL-L| 命令时 (整个屏幕被更新)。例如,要高亮显示光标下的单词:/\k*\%#\k*
当设定了 'hlsearch' 时,你移动光标并作更改就能清楚的看到更新的情况。 */\%l* */\%>l* */\%<l* \%23l 在一个指定的行内进行匹配。 \%<23l 在一个指定的行上方进行匹配。 \%>23l 在一个指定的行下方进行匹配。 这三个可以被用来匹配缓冲内的特定行。"23" 可以是任何行号。第一行为 1。{Vi 无此功能}
警告:当插入和删除行时 Vim 不会自动更新匹配。这意味着语法加亮会出错。 例如,要高亮显示光标所在行::exe '/\%' . line(".") . 'l.*'
当 'hlsearch' 被设定时,你的移动会很清楚的被显示 (仅当匹配被更新时) */\%c* */\%>c* */\%<c* \%23c 在一个指定的列内进行匹配。 \%<23c 在一个指定的列前进行匹配。 \%>23c 在一个指定的列后进行匹配。 这三个可以被用来匹配缓冲内的特定列。"23" 可以是任何列号。第一列为 1。 事实上,列以字节计算 (因此对多字节字符来说是不准确的)。{Vi 无此功能}
警 告:当插入和删除字符时 Vim 并不自动更新匹配。这意味着语法高亮很 快就不正确了。 例如,要高亮显示光标所在列::exe '/\%' . col(".") . 'c'
当 'hlsearch' 被设定时,你的移动会很清楚的被显示 (仅当匹配被更新时) 一个匹配第 44 列单个字节的例子:/\%>43c.\%<46c
注意
:"\%<46c" 匹配第 45 列,而 "." 匹配 44 列的一个字节。 */\%v* */\%>v* */\%<v* \%23v 匹配指定虚拟列。 \%<23v 匹配指定虚拟列之前。 \%>23v 匹配指定虚拟列之后。 这三个可以被用来匹配缓冲或字符串中指定的虚拟列。当匹配一个不在窗口内 的缓冲时,当前窗口的选项值将被使用 (如, 'tabstop')。 "23" 可以是任何 列号。第一列为 1。注意
默写虚拟列位置永远无法被匹配,因为它们被包含在一个制表符或者其它 占用超过一个屏幕字符的特殊字符。{Vi 无此功能}
警 告: 当删除和插入字符时 Vim 不会自动更新匹配。这意味着语法高亮很快 就变得不对了。 例如,要高亮显示所有位于虚拟第 72 列的字符:/\%>72v.*
当设定了 'hlsearch' 选项时,如果你移动光标并做一些改动,更新的情况就 会清楚的被显示了。 要匹配直到第 17 列的文本:/.*\%17v
第 17 没有被包括,因为那是 "\%17v" 匹配的地方,而这是一个零宽度 |/zero-width| 匹配,第 17 列没有被包括在匹配之中。这个也一样:/.*\%<18v
字符类:{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* \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]$ 同上 如果在集合前加上 "\_" 的话,该模式也将匹配行尾,这等价于集合里加上 "\n"。 "^" 开始的模式也可以匹配行尾。因此 "\_[^ab]" 将匹配行尾以及任意 非 "a" 或 "b" 的字符。这使其与 Vi 兼容:没有 "\_" 或 "\n"时,集合不匹 配行尾。 如果集合以 "^" 开始,它匹配任意_不在_集合内的字符:"[^xyz]" 匹配任何 不是 'x', 'y' 和 'z' 的字符。 - 如果集合中的两个字符被以 '-' 隔开,表示它们之间的所有 ASCII 字符。例 如, "[0-9]" 匹配任何十进制数位。 - 一个字符类表达式被解释为该字符类代表的字符集合。Vim 支持以下字符类:名称 内容
*[:alnum:]* [:alnum:] 字母和数字 *[:alpha:]* [:alpha:] 字母 *[:blank:]* [:blank:] 空格和制表字符 *[:cntrl:]* [:cntrl:] 控制字符 *[:digit:]* [:digit:] 十进制数位 *[:graph:]* [:graph:] 可打印字符 (不包括空格) *[:lower:]* [:lower:] 小写字母 (使用 'ignorecase' 时代表所有 字母) *[:print:]* [:print:] 可打印字符 (包括空格) *[:punct:]* [:punct:] 标点字符 *[:space:]* [:space:] 空白字符 *[:upper:]* [:upper:] 大写字母 (使用 'ignorecase' 时代表所有 字母) *[:xdigit:]* [:xdigit:] 十六进制数位 *[:return:]* [:return:] 字符<CR>
*[:tab:]* [:tab:] 字符<Tab>
*[:escape:]* [:escape:] 字符<Esc>
*[:backspace:]* [:backspace:] 字符<BS>
字符类表达式中的方括号是对于集合的补充。例如,下面的模式是一个 UNIX 文件名: "[-./[:alnum:]_~]\+"。即一组至少有一个字符的字符列表。 其中每一个字符是 '-','.','/',字母,数字,'_' 或 '~' 中的一个。 这些项仅对 8 位字符有效。 */\]* - 要在集合之内包括字符 ']',^','-' 或 '\',只需在该字符前加上反斜杠: "[xyz\]]","[\^xyz]","[xy\-z]" 和 "[xyz\\]"。 (备注
: POSIX 不支持这 种反斜杠的用法)。 对于 ']' 你也可以将其作为第一个字符 (但可能在 "^" 之后) 而无须转义: "[]xyz]" 或 "[^]xyz]"{Vi 无此功能}
。 对于 '-' 你也可以将其作为第一个或最后一个字符:"[-xyz]", "[^-xyz]" 或 "[xyz-]"。 对于 '\' 你也可以将其放置在非 "^]-\bertn"的任何一个别的字符之前而无 须转义:"[\xyz]" 匹配 '\','x','y' 及 'z'。但是用 "\\" 好些,因为将 来的扩展可能会在 '\' 之后使用其它字符。 - 当 'cpoptions' 中不包括 'l' 标志时,以下转义是可用的{Vi 无此功能}
: \e<Esc>
\t<Tab>
\r<CR>
(不是行尾!) \b<BS>
备注
: 这些额外的转义码不能用在方括号 [] 之内! - 用集合来匹配可能会很慢。因为每个字符都要和集合中的每一个字符作比较。 尽可能使用上面提到的匹配原。例如:同样是匹配数字,"\d" 要比 "[0-9]" 快的多。 */\%[]* *E69* *E70* *E369* \%[] 一个可能匹配的匹配原列表。它总能匹配,但试图匹配尽量多的匹配原,而在第 一个不匹配的地方终止。例如:/r\%[ead]
匹配 "r","re","rea" 或者 "read"。最长可能的匹配被采用。下面例子可以 用来匹配 Ex 命令 "function",其中 "fu" 是必须的而 "nction" 是可选的:/\
这里用到了单词结尾 "\>" 来避免匹配 "full" 中的 "fu"。 当要匹配的不是普通字符时,问题就变得更复杂了。你不一定会经常这样做,但 这么做的确是可能的。例如:<fu\%[nction]\>
/\
匹配 "r","re","ro","rea","roa","read" 及 "road"。<r\%[[eo]ad]\>
{only 只在编译时加入 +syntax 特征时有效}
7. 忽略大小写 */ignorecase*
如果选项 'ignorecase' 被设定为打开的话,一般字符的大小写就会被忽略。当模式 只包含小写字符时 'smartcase' 会被设成忽略大小写。 */\c* */\C* 如果模式的任何位置出现了 "\c",整个模式会被象打开 'ignorecase' 一样被处理。 真正的 'ignorecase' 和 'smartcase' 的值会被忽略。"\C" 的效果恰好相反: 强制 对整个模式匹配大小写。{only Vim 支持 \c 和 \C}
注意
'ignorecase',"\c" 和 "\C" 对字符类无效。 例如:模式 'ignorecase' 'smartcase' 匹配
foo off - foo foo on - foo Foo FOO Foo on off foo Foo FOO Foo on on Foo \cfoo - - foo Foo FOO foo\C - - foo */\Z* 如果模式的任何位置出现了 "\Z",合成用字符将被忽略。这样,只有基本字符需要匹配, 合成用字符或有不同甚至其数量也可以不定。这一功能只在 'encoding' 为 'utf-8' 时 有意义。 技术细节: *NL-used-for-Nul* 文件中的<Nul>
字符在内存中被存储为<NL>
。显示为 "^@"。翻译是在读写文件时完成 的。为了在查找模式中匹配<Nul>
你可以使用CTRL-@
或 "CTRL-V
000"。这应该不出你 的所料。内部该字符被替换为<NL>
。不寻常的是键入CTRL-V
CTRL-J
同样插入一个<NL>
,因此也搜索文件中的<Nul>
.{Vi 则完全不能处理文件中的
*CR-used-for-NL* 当 'fileformat' 为 "mac" 时,<Nul>
字符}<NL>
字符在内部储存为<CR>
。显示为 "^M"。其它的 类似以<NL>
作为<Nul>
的用法。 在作表达式求值时,模式中的<NL>
字符匹配字符串中的<NL>
。用 "\n" (反斜杠 n) 来 匹配<NL>
在这里是行不通的,它仅对缓冲内的文本有效。 *pattern-multi-byte* 模式匹配对于多字节字符同样适用。大体上使用并无区别,不过要注意
无效字节可能引起 的问题,一个包含无效字节的模式永远不会得到匹配。
8. 与 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 code}
) - 条件表达式: (?(condition)true-expr|false-expr) 下面是 Vim 独有的: - 改变模式的 'magic' 属性: \v \V \m \M 对于避免反斜杠非常有用) - 可选匹配原序列: \%[atoms] - \& (相对于 \| 来说 就象 "与" 相对于 "或";它强迫多个模式在同一个位置匹配) - 通过行/列号匹配: \%5l \%5c \%5v - 限制正则表达式的 "返回值": \zs \ze
9. 高亮显示匹配 *match-highlight*
*:mat* *:match* :mat[ch]{group}
/{pattern}
/ 定义一个要在当前窗口高亮显示的模式。会被以{group}
高亮。例::highlight MyGroup ctermbg=green guibg=green
:match MyGroup /TODO/
除了 // 任何字符都可以被用来表示一个{pattern}
的开始和结束。 要当心某些特殊的字符,例如 '"' 和 '|'。{group}
在该命令被执行时必须是已经定义好的。该匹配会否决 'hlsearch' 所定义的高亮。 'ignorecase' 不起作用。你得在模式中使用 |/\c| 来达到目的。 否则大小写是区分的。注意
使用 'hlsearch' 高亮显示上次使用的查找模式对所有窗口都 有效,而以 ":match" 定义的模式仅仅对当前窗口生效。当切换至 另一个缓冲时,该设定被保留。 另一个例子,高亮显示所有虚拟第 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 清除前面定义的匹配模式。 vim:tw=78:ts=8:ft=help:norl:
Generated by vim2html on 2006年 06月 24日 星期六 00:27:59 UTC