PATTERN
*pattern.txt* For Vim version 6.2. 最近更新:2005年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. 模式项总揽 |pattern-overview| 4. 多项 |pattern-multi-items| 5. 普通匹配原 |pattern-atoms| 6. 忽略大小写 |/ignorecase| 7. 与 Perl 匹配模式的比较 |perl-patterns| 8. 高亮显示匹配 |match-highlight|
1. 查找命令 *search-commands* *E486* */* /{pattern}
[/]<CR>
向前查找第[count]
次出现{pattern}
的地方 (不包含) /{pattern}
/{offset}
<CR>
向前查找第[count]
次出现{pattern}
的地方 并向上或下移动 |{offset}| 行。 */<CR>* /<CR>
向前查找第[count]
次出现处,使用上次的模式 |last-pattern| 以及 |{offset}|. //{offset}
<CR>
向前查找第[count]
次出现处,使用上次的模式 |last-pattern| 以及新偏移 |{offset}|. 若{offset}
为空不使用任何偏移。 *?* ?{pattern}
[?]<CR>
向后查找第[count]
次出现{pattern}
的地方 (不包含) ?{pattern}
?{offset}
<CR>
S向后查找第[count]
次出现{pattern}
的地方 并向上或下移动 |{offset}| 行。 *?<CR>* ?<CR>
向后查找第[count]
次出现处,使用上次的模式 |last-pattern| 以及 |{offset}|. ??{offset}
<CR>
向后查找第[count]
次出现处,使用上次的模式 |last-pattern| 以及新偏移 |{offset}|. 若{offset}
为空不使用任何偏移。 *n* n 将上次的 "/" 或 "?" 重复[count]
次。 |last-pattern|{Vi: 无次数}
*N* N 将上次的 "/" 或 "?" 在反方向上重复[count]
次。 |last-pattern|{Vi: 无次数}
*star* *E348* *E349* * 向前查找第[count]
次出现距离当前光标最近的单词的地方。 用于查找的单词是一下的先符合条件的: 1. 光标下的关键字 |'iskeyword'| 2. 当前行内的光标后的第一个关键字。 3. 光标下的非空白单词 4. 当前行内的光标后的第一个非空白单词 只查找整字,象和命令 "/\<keyword\>
" 一样。(不包含){not in Vi}
使用 'ignorecase', 'smartcase' 没有。 *#* # 同 "*", 但向后查找。 磅符号 (字符 163) 也可。如果 "#" 的功能和退格键一样,试着在启动 Vim 前使用 "stty erase<BS>
" (<BS>
是CTRL-H
或真的退格键).{not in Vi}
*gstar* g* 同 "*",但不使用 "\<" 和 "\>
"。这样查找就会匹配非整字的 地方。{not in Vi}
*g#* g# 同 "#",但不使用 "\<" 和 "\>
"。这样查找就会匹配非整字的 地方。{not in Vi}
*gd* gd 跳转至局部声明。当光标下是一个局部变量时,此命令会跳转 到该变量被声明的地方。首先,Vim 会查找当前函数的起始处。 就象使用 "[[" 一样。如果找不到会停止在第一行。如果找到, Vim 会向后直到找到一个空行,然后从这里开始向前查找光标 下的关键字,就象 "*"。看起来象注视的行会被忽略。 (见 'comments' 选项). 注意 这并非总有效。Vim 不会做语法分析。它仅仅查找关键 字的匹配。如果需要搜索头文件的话,可以使用 |include-search| 列出的命令。 这个命令之后,可以使用 |n| 向前查找下一个匹配 (不能向后).{not in Vi}
*gD* gD 跳转至全局声明。当光标下是一个全局变量时,此命令会跳转 到该变量被声明的地方。这和 "gd" 命令一样,不过查找总是 从第一行开始。{not in 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}* 这些命令查找一个指定的模式。对于 "/" 和 "?" 命令可以指定一个额外的偏移量。有两 种偏移:行偏移和字符偏移。{字符偏移不适用于 Vi}
偏移用来指定光标相对于找到的匹配的位置:[num]
[num]
行向下,列 1 +[num]
[num]
行向下,列 1 -[num]
[num]
行向上,列 1 e[+num]
[num]
字符向右 (从匹配结束处算起) e[-num]
[num]
字符向左 (从匹配结束处算起) s[+num]
[num]
字符向右 (从匹配开始 (start) 处算起) s[-num]
[num]
字符向左 (从匹配开始 (start) 处算起) b[+num]
[num]
字符向左 (从匹配开始 (begin) 处算起) b[-num]
[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 change until end of match
bar
<Esc>
type replacement//
<CR>
go to start of next matchc//e change until end of match
beep
<Esc>
type another replacementetc.
*//;* *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' flag: "/..." 前进 1 至 3 个字符 不带 'c' flag: "/..." 前进 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(|
3. 模式项总揽 *pattern-overview* 多项总揽。 */multi* *E61* *E62* 下面给处一些解释和例子,包括链接。 *E64*multi
'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, 象匹配一整个模式 (*) |/\@=| \@= \@= nothing, requires a match |/zero-width| (*) |/\@!| \@! \@! nothing, requires NO match |/zero-width| (*) |/\@<=| \@<= \@<= nothing, requires a match behind |/zero-width| (*) |/\@<!| \@<! \@<! nothing, requires NO match behind |/zero-width| (*) (*){not in Vi}
普通原总揽。 */ordinary-atom* 下面给处一些解释和例子,包括链接。ordinary atom
magic nomagic matches
|/^| ^ ^ 行首 (在模式起始) |/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| 字符类{not in 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 第一个 \(\) 匹配的字符{not in 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 ignore differences in Unicode "combining characters". Useful when searching voweled Hebrew or Arabic text.Example matches
\<\I\i* 或 \<\h\w* \<[a-zA-Z_][a-zA-Z0-9_]* 一个标识符 (例如,在一个 C 程序里)。 \(\.$\|\. \) 一个英文句号后跟<EOL>
或一个空格。 [.!?][])"']*\($\|[ ]\) 一个匹配英文句子结尾的模式。几乎和 ")" 定义的一样。 cat\Z 匹配 "cat" 和 "ca虁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 supports \m, \M, \v and \V}
建议始终将 'magic' 选项保持在缺省值 - 'magic'。这可以避免移植性的麻烦。要使 模式不受该选项值的影响,在模式前面加上 "\m" 或 "\M"。
4. 多项 *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* \+ 匹配一个或更多前面的匹配原。尽可能多。{not in Vi}
例 匹配
^.\+$ 任意空行 \s\+ 一个以上的空白字符 */\=* \= 匹配 0 或 1 个前面的匹配原。尽可能多。{not in Vi}
例 匹配
foo\= "fo" 和 "foo" */\?* \? 和 \= 一样。不能和 "?" 命令中使用。{not in 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 does not have any of these}
n 和 m 是正的十进制数 如果一个 "-" 紧接在 "{" 之后,那么最短匹配优先算法将被启用 (见下面的例子)。 In particular, "\{-}
" is 特别的,"\{-}
" 和 "*" 一样,只不过使用了最短匹配优先算法。但 是: 一个 先前开始的匹配拥有比最短匹配高的优先级: "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\}
. */\@=* \@= 以零宽度匹前面的匹配原。{not in Vi}
象 Perl 中的 '(?=pattern)".例 匹配
foo\(bar\)\@= "foobar" 中的 "foo" foo\(bar\)\@=foo 空 */zero-width* 当使用 "\@=" (或 "^", "$", "\<", "\>
") 时匹配中不包括任何字符。这些 字符仅仅是被用来检查能否构成一个匹配的。这很容易搞错。因为后续的项 会被在同样位置作匹配。上面的最后一个例子不会匹配 "foobarfoo",因为 Vim 会尝试在 "bar" 匹配的同样地方匹配 "foo"。 注意 使用 "\&" 同使用 "\@=" 是一样的: "foo\&.." 和 "\(foo\)\@=.." 一样。但用 "\&" 容易些,你可以省了那些括号。 */\@!* \@! Matches with zero width if the preceding atom does NOT match at the current position |/zero-width|{not in Vi}
象 Perl 中的 '(?!pattern)"。例如 匹配
foo\(bar\)\@! 任意后面不带 "bar" 的 "foo" a.\{-}
p\@! "a", "ap", "app", 等。后面不带 "p" Using "\@!" is tricky, because there are many places where a pattern does not match. "a.*p\@!" will match from an "a" to the end of the line, because ".*" can match all characters in the line and the "p" doesn't match at the end of the line. "a.\{-}
p\@!" will match any "a", "ap", "aap", etc. that isn't followed by a "p", because the "." can match a "p" and "p\@!" doesn't match after that. You can't use "\@!" to look for a non-match before the matching position: "\(foo\)\@!bar" will match "bar" in "foobar", because at the position where "bar" matches, "foo" does not match. To avoid matching "foobar" you could use "\(foo\)\@!...bar", but that doesn't match a bar at the start of a line. Use "\(foo\)\@<!bar". */\@<=* \@<= Matches with zero width if the preceding atom matches just before what follows. |/zero-width|{not in Vi}
Like '(?<=pattern)" in Perl, but Vim allows non-fixed-width patterns.Example matches
\(an\_s\+\)\@<=file "file" after "an" and white space or an end-of-line For speed it's often much better to avoid this multi. Try using "\zs" instead |/\zs|. To match the same as the above example: an\_s\+\zsfile "\@<=" and "\@<!" check for matches just before what follows. Theoretically these matches could start anywhere before this position. But to limit the time needed, only the line where what follows matches is searched, and one line before that (if there is one). This should be sufficient to match most things and not be too slow. The part of the pattern after "\@<=" and "\@<!" are checked for a match first, thus things like "\1" don't work to reference \(\) inside the preceding atom. It does work the other way around:Example matches
\1\@<=,\([a-z]\+\) ",abc" in "abc,abc" */\@<!* \@<! Matches with zero width if the preceding atom does NOT match just before what follows. Thus this matches if there is no position in the current or previous line where the atom matches such that it ends just before what follows. |/zero-width|{not in Vi}
Like '(?<!pattern)" in Perl, but Vim allows non-fixed-width patterns. The match with the preceding atom is made to end just before the match with what follows, thus an atom that ends in ".*" will work. Warning: This can be slow (because many positions need to be checked for a match).Example matches
\(foo\)\@<!bar any "bar" that's not in "foobar" \(\/\/.*\)\@\<!in "in" which is not after "//" */\@>* \@> 象匹配一整个模式一样匹配前面的原。{not in Vi}
类似 Perl 中的 '(?>pattern)".例子 匹配
\(a*\)\@>a 空 ("a*" 用尽了所有的 "a",后面不可能有了) 这象匹配一整个模式一样匹配前面的原。如果无法匹配,不会用较短的子模式 来重试。注意 观察这两者的不同:"a*b" 和 "a*ab" 都匹配 "aaab",但是后者 中的 "a*" 仅仅匹配前两个 "a"。"\(a*\)\@>ab" 不会匹配 "aaab",因为 "a*" 匹配了 "aaa" (尽可能多个 "a"),导致 "ab" 无法匹配。
5. 普通匹配原 *pattern-atoms* 一个普通匹配原可能是: */^* ^ 在模式起点或在 "\|", "\(", "\%(", "\n" 之后: 匹配行首;在其它位置 匹配 '^' 字符。 |/zero-width|例如 匹配
^beep( C 函数 "beep" 开始的地方 (很可能). */\^* \^ 匹配原字符 '^'。可以用于任何位置。 */\_^* \_^ 匹配行首。|/zero-width| 可以被用于任何位置。例子 匹配
\_s*\_^foo 空白字符及空行,后接行首的 "foo"。 */$* $ 在模式终点或 "\|", "\)" ("\v" 之后的 "
|", ")" ) 之前: 匹配行尾<EOL>
; 其它位置,匹配原字符 '$'。|/zero-width| */\$* \$ 匹配原字符 '$'。可以被用于任何位置。 */\_$* \_$ 匹配行尾。|/zero-width| 可以被用于任何位置。例子 匹配
foo\_$\_s* "foo" 在行尾,后接空白字符及空行 . (with 'nomagic': \.) */.* */\.* 匹配任何单个字符,不包括行尾。 */\_.* \_. 匹配任何单个字符,或行尾。当心:"\_.*" 会一直匹配到缓冲结尾! */\<* \< 匹配单词起点:下一个字符是单词的首字符。'iskeyword' 选项指定那些是 组成单词的字符。|/zero-width| */\>* \> 匹配单词终点:前一个字符是单词的尾字符。'iskeyword' 选项指定那些是 组成单词的字符。|/zero-width| */\zs* \zs 匹配任何位置,并将匹配起始处置于该处: 下一个字符将是整个匹配的第一个 字符。|/zero-width| 可以被多次使用,最后一个分支中的将被选中。 例如: "^\s*\zsif" 匹配行首的 "if",忽略所有空白字符。{not in Vi}
{not available when compiled without the +syntax feature}
*/\ze* \ze 匹配任何位置,并将匹配结尾处置于该处: 前一个字符将是整个匹配的最后一个 字符。|/zero-width| 可以被多次使用,最后一个分支中的将被选中。 例如: "end\ze\(if\|for\)" 匹配 "endif" 和 "endfor" 中的 "end"。{not in Vi}
{not available when compiled without the +syntax feature}
*/\%^* *start-of-file* \%^ 匹配文件头。当用于一个字符串时,匹配字符串起始处。{not in Vi}
例如,要查找一个文件中首次出现 "VIM" 的地方:/\%^\_.\
*/\%$* *end-of-file* \%$ 匹配文件尾。当用于一个字符串时,匹配字符串结束处。{-}
\zsVIM{not in Vi}
注意 下面的模式不匹配文件中的最后一个 "VIM":/VIM\_.\
它会找到下一个 VIM,因为其后的部分总会匹配。这个才能匹配文件 中的最后一个 "VIM":{-}
\%$/VIM\ze\(\(VIM\)\@!\_.\)*\%$
这使用了 |/\@!| 来确定在第一 "VIM" 之后无法再次匹配 "VIM"。 从文件尾部向前搜索会容易些! */\%#* *cursor-position* \%# 匹配光标位置。仅对显示于窗口内的缓冲有效。{not in Vi}
警 告: 如果使用了该模式之后光标被移动,结果会成为无效的。Vim 不会自动的 更新匹配。这对语法高亮和 'hlsearch' 有更大的关系。换言之: 在光标移动时 显示并不因此而更新。Vim 只更新改动的行 (整行被更新) 或用户使用 |CTRL-L| 命令时 (整个屏幕被更新)。例如,要高亮显示光标下的单词:/\k*\%#\k*
当设定了 'hlsearch' 时,你移动光标并作更改就能清楚的看到更新的情况。 */\%l* */\%>l* */\%<l* \%23l 在一个指定的行内进行匹配。 \%<23l 在一个指定的行上方进行匹配。 \%>23l 在一个指定的行下方进行匹配。 这三个可以被用来匹配缓冲内的特定行。"23" 可以是任何行号。第一行为 1。{not in Vi}
警告:当插入和删除行时 Vim 不会自动更新匹配。这意味着语法加亮会出错。 例如,要高亮显示光标所在行::exe '/\%' . line(".") . 'l.*'
当 'hlsearch' 被设定时,你的移动会很清楚的被显示 (仅当匹配被更新时) */\%c* */\%>c* */\%<c* \%23c 在一个指定的列内进行匹配。 \%<23c 在一个指定的列前进行匹配。 \%>23c 在一个指定的列后进行匹配。 这三个可以被用来匹配缓冲内的特定列。"23" 可以是任何列号。第一列为 1。 事实上,列以字节计算 (因此对多字节字符来说是不准确的)。{not in Vi}
警 告:当插入和删除字符时 Vim 并不自动更新匹配。这意味着语法高亮很 快就不正确了。 例如,要高亮显示光标所在列::exe '/\%' . col(".") . 'c'
当 'hlsearch' 被设定时,你的移动会很清楚的被显示 (仅当匹配被更新时) */\%v* */\%>v* */\%<v* \%23v 匹配指定虚拟列。 \%<23v 匹配指定虚拟列之前。 \%>23v 匹配指定虚拟列之后。 这三个可以被用来匹配缓冲或字符串中指定的虚拟列。当匹配一个不在窗口内 的缓冲时,当前窗口的选项值将被使用 (如, 'tabstop')。 "23" 可以是任何 列号。第一列为 1。 注意 默写虚拟列位置永远无法被匹配,因为它们被包含在一个制表符或者其它 占用超过一个屏幕字符的特殊字符。{not in Vi}
警 告: 当删除和插入字符时 Vim 不会自动更新匹配。这意味着语法高亮很快 就变得不对了。 例如,要高亮显示所有位于虚拟第 72 列的字符:/\%>72v.*
当设定了 'hlsearch' 选项时,如果你移动光标并做一些改动,更新的情况就 会清楚的被显示了。 要匹配直到第 17 列的文本:/.*\%17v
第 17 没有被包括,因为那是 "\%17v" 匹配的地方,而这是一个零宽度 |/zero-width| 匹配,第 17 列没有被包括在匹配之中。这个也一样:/.*\%<18v
字符类:{not in 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* \_x 其中 x 可以是以上任意一个字符:包括行尾的字符类 (字符类结束) \e 匹配<Esc>
*/\e* \t 匹配<Tab>
*/\t* \r 匹配<CR>
*/\r* \b 匹配<BS>
*/\b* \n 匹配行尾 */\n* 当对一个字符串而不是缓冲进行匹配时,匹配一个本意的换行字符。 ~ 匹配上次给出的替换字串 */~* */\~* \(\) 一个由转意的括号括起来的模式。 */\(* */\(\)* */\)* 例:"\(^a\)" 匹配行首的 'a'。 *E51* *E54* *E55* \1 匹配第一个子表达式匹配的字串 */\1* *E65*{not in Vi}
例如: "\([a-z]\).\1" 匹配 "ata", "ehe", "tot", 等. \2 象 "\1",但使用第二子表达式, */\2* ... */\3* \9 象 "\1", 但使用第三子表达式。 */\9* 备注: 各组的标号是基于那一个 "\(" 先出现 (自左至右),而非那一个先匹配。 \%(\) 一个由转意的括号括起来的模式。 */\%(\)* */\%(* *E53* 类似 \(\),但不算作一个子表达式。这样做允许使用更多的组,并且处理时会 稍快些。{not in 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]"{not in Vi}
. 对于 '-' 你也可以将其作为第一个或最后一个字符: "[-xyz]", "[^-xyz]" 或 "[xyz-]"。对于 '\' 你也可以将其放置在任意不在 "^]-\bertn" 之内的字 符:"[\xyz]" 匹配 '\', 'x', 'y' 及 'z'。但是用 "\\" 好些,因为将来的 扩展可能会在 '\' 之后使用其它字符。 - 当 'cpoptions' 中不包括 'l' 标志时,以下转换是可用的{not in 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]\>
{not available when compiled without the +syntax feature}
6. 忽略大小些 */ignorecase* 如果选项 'ignorecase' 被设定为打开的话,一般字符的大小些就会被忽略。当模式 只包含小写字符时 'smartcase' 会被设成忽略大小写。 */\c* */\C* 当 "\c" 出现在模式中任何地方时,整个模式会被象打开 'ignorecase' 一样被处理。 真正的 'ignorecase' 和 'smartcase' 的值会被忽略。"\C" 的效果恰好相反: 强制 对整个模式匹配大小写。{only Vim supports \c and \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* When "\Z" appears anywhere in the pattern, composing characters are ignored. Thus only the base characters need to match, the composing characters may be different and the number of composing characters may differ. Only relevant when 'encoding' is "utf-8". 技术细节: *NL-used-for-Nul* 文件中的<Nul>
字符在内存中被存储为<NL>
。显示为 "^@"。翻译是在读写文件时完成 的。为了在查找模式中匹配<Nul>
你可以使用CTRL-@
或 "CTRL-V
000"。这应该不出你 的所料。内部该字符被替换为<NL>
。不寻常的是键入CTRL-V
CTRL-J
同样插入一个<NL>
, 因此也搜索文件中的<Nul>
.{Vi cannot handle
*CR-used-for-NL* 当 'fileformat' 为 "mac" 时,<Nul>
characters in the file at all}<NL>
字符在内部储存为<CR>
。显示为 "^M"。其它的 类似以<NL>
作为<Nul>
的用法。 在作表达式求值时,模式中的<NL>
字符匹配字符串中的<NL>
。用 "\n" (反斜杠 n) 来 匹配<NL>
在这里是行不通的,它仅对缓冲内的文本有效。 *pattern-multi-byte* 匹配模式对于多字节字符同样适用。大多数情况下,都不会有例外。但是无效的字节 可能会因此麻烦,一个包含无效字节的模式很可能永远不会匹配。
7. 与 Perl 模式的比较 *perl-patterns*
Vim 中的正则表达式和 Perl 的在功能上来说非常相似。它们之间的区别大多数是表达
方法;这里给出一个它们之间的区别的总结:
兼容性 Vim 方言 Perl 方言
强制不区分大小写 \c (?i) 强制区分大小写 \C (?-i) backref-less grouping \%(atom) (?:atom) 保守修饰符 \{-n,m}
*?, +?, ??,{}
? 0 宽度匹配 atom\@= (?=atom) 0 宽度否匹配 atom\@! (?!atom) 0 宽度前匹配 atom\@<= (?<=atom) 0 宽度前否匹配 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] - \& (which is to \| what "and" is to "or"; it forces several branches to match at one spot) - 通过行/列号匹配: \%5l \%5c \%5v - 限制正则表达式的 "返回值": \zs \ze
8. 高亮显示匹配 *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 /\%
注意 用两个项是为了匹配那些占用超过一列的字符,例如 TAB。 :mat[ch] :mat[ch] none 清楚前面定义的匹配模式。 vim:tw=78:ts=8:ft=help:norl:<8v.\%>
7v/
Generated by vim2html on Wed Mar 2 23:05:27 GMT 2005