模式
Nvim :help
页面,生成 自 源代码 使用 tree-sitter-vimdoc 解析器。
模式和搜索命令
/ /{pattern}[/]<CR> 向前搜索
{pattern}
的第 [count] 次出现,
排他。
/{pattern}/{offset}<CR> 向前搜索
{pattern}
的第 [count] 次出现,并向上或向下移动
{offset} 行。
按行。
? ?{pattern}[?]<CR> 向后搜索
{pattern}
的第 [count] 次出现,
排他。
?{pattern}?{offset}<CR> 向后搜索
{pattern}
的第 [count] 次出现,并向上或向下移动
{offset} 行
按行。
n n 重复最新的 "/" 或 "?" [count] 次。如果光标没有移动,则重复搜索,并将计数增加 1。
last-pattern
# # 与 "*" 相同,但向后搜索。井号(字符 163)也适用。如果 "#" 键用作退格键,请尝试在启动 Vim 之前使用 "stty erase
<BS>
"(
<BS>
是
CTRL-H
或真正的退格键)。
v_#-default
{Visual}
# 在可视模式下,向后搜索当前选择内容。
default-mappings
gstar g* 与 "*" 相同,但不围绕单词放置 "\<" 和 "\>"。这使得搜索也能找到不是整个单词的匹配项。
g# g# 与 "#" 相同,但不围绕单词放置 "\<" 和 "\>"。这使得搜索也能找到不是整个单词的匹配项。
gd gd 转到局部声明。当光标位于局部变量上时,此命令将跳转到其声明位置。这是为 C 代码而设计的,在其他语言中可能无法正常工作。首先,Vim 搜索当前函数的开头,就像 "[[“ 一样。如果找不到,则搜索在第 1 行停止。如果找到了,Vim 会回溯,直到找到空白行。从该位置,Vim 会搜索光标下的关键字,就像 "*" 一样,但看起来像注释的行会被忽略(参见
'comments' 选项)。请注意,这不能保证能正常工作,Vim 不会真正检查语法,它只是搜索与关键字的匹配项。如果还需要搜索包含的文件,请使用
include-search 中列出的命令。执行此命令后,
n 会向前搜索下一个匹配项(而不是向后)。
gD gD 转到全局声明。当光标位于在文件中定义的全局变量上时,此命令将跳转到其声明位置。这与 "gd" 的工作方式相同,只是关键字搜索始终从第 1 行开始。
1gd 1gd 与 "gd" 相同,但会忽略在光标位置之前结束的 {} 块内的匹配项。
1gD 1gD 与 "gD" 相同,但会忽略在光标位置之前结束的 {} 块内的匹配项。
CTRL-C CTRL-C 中断当前(搜索)命令。在普通模式下,任何待处理的命令都会被中止。
在键入搜索模式时,如果
'incsearch' 选项处于打开状态,则会显示当前匹配项。请记住,你仍然需要使用
<CR>
完成搜索命令才能将光标实际定位在显示的匹配项上。或者使用
<Esc>
放弃搜索。
当
'shortmess' 不包含 "S" 标志时,Vim 会自动显示光标所在的索引。这可能看起来像这样
[1/5] Cursor is on first of 5 matches.
[1/>99] Cursor is on first of more than 99 matches.
[>99/>99] Cursor is after 99 match of more than 99 matches.
[?/??] Unknown how many matches exists, generating the
statistics was aborted because of search timeout.
注意:计数不考虑偏移量。
如果找不到匹配项,你会收到错误:
E486 模式未找到 请注意,对于
:global
命令,你将收到正常的提示信息 "模式未找到",以保持与 Vi 的兼容性。对于
:s 命令,可以使用 "e" 标志来避免错误提示信息
:s_flags。
偏移量给出相对于找到的匹配项的光标位置: [num] [num] 行向下,在第 1 列 +[num] [num] 行向下,在第 1 列 -[num] [num] 行向上,在第 1 列 e[+num] [num] 个字符在匹配项末尾的右侧 e[-num] [num] 个字符在匹配项末尾的左侧 s[+num] [num] 个字符在匹配项开头的右侧 s[-num] [num] 个字符在匹配项开头的左侧 b[+num] [num] 与上面的 s[+num] 相同(助记符:开始) b[-num] [num] 与上面的 s[-num] 相同(助记符:开始) ;{pattern} 执行另一个搜索,参见
//;
如果给出了 "-" 或 "+" 但省略了 [num],则使用计数 1。当使用 'e' 包含偏移量时,搜索变为包含式(光标落到的字符包含在操作中)。
示例
模式 光标位置
/test/+1 "test" 下面的第一行,在第 1 列 /test/e 在 "test" 的最后一个 t 上 /test/s+2 在 "test" 的 's' 上 /test/b-3 在 "test" 前三个字符
如果在操作符之后使用这些命令之一,则光标在搜索之前和之后的位置之间的字符将受到影响。但是,如果给出了行偏移量,则两个光标位置之间的整个行将受到影响。
搜索匹配项并使用另一个单词更改匹配项的示例
/foo<CR> find "foo"
c//e<CR> change until end of match
bar<Esc> type replacement
//<CR> go to start of next match
c//e<CR> change until end of match
beep<Esc> type another replacement
etc.
//; E386 一个非常特殊的偏移量是 ";" 后面跟着另一个搜索命令。例如
/test 1/;/test
/test.*/+1;?ing?
第一个首先找到 "test 1" 的下一个出现位置,然后找到 "test" 的第一个出现位置。
这就像在彼此之后执行两个搜索命令,只是
它可以用作操作符之后的单个移动命令。
以下 "n" 或 "N" 命令的方向来自第一个搜索命令。
如果发生错误,光标根本不会移动。
last-pattern 上次使用的模式和偏移量会被记住。它们可以用来重复搜索,可能在另一个方向或使用另一个计数。请注意,会记住两个模式:一个用于“正常”搜索命令,另一个用于替换命令 ":s"。每次给出空模式时,都会使用先前使用的模式。但是,如果之前没有搜索命令,则会使用先前的替换模式(如果可能)。
清除上次使用的搜索模式
:let @/ = ""
这不会将模式设置为一个空字符串,因为这会导致它在任何地方匹配。模式被真正清除,就像启动 Vim 时一样。
搜索通常会跳过不会移动光标的匹配项。下一个匹配项是在下一个字符处找到还是在跳过的匹配项之后找到,取决于
'cpoptions' 中的 'c' 标志。参见
cpo-c。使用 'c' 标志:"/..." 向前移动 1 到 3 个字符,不使用 'c' 标志:"/..." 向前移动 1 个字符 这种使用 'c' 标志时的不可预测性是由于从第一列开始搜索,跳过匹配项,直到在光标位置之后找到一个匹配项造成的。
向后搜索时,搜索从行的开头开始,使用
'cpoptions' 中的 'c' 标志,如上所述。然后使用光标位置之前的最后一个匹配项。
在 Vi 中,":tag" 命令在搜索标签时设置最后一个搜索模式。在 Vim 中,这不会发生,之前的搜索模式仍然会被记住,除非
'cpoptions' 中存在 't' 标志。搜索模式始终被放入搜索历史记录中。
如果
'wrapscan' 选项开启(默认),搜索会环绕缓冲区末尾。如果
'wrapscan' 未设置,则向后搜索将在开头停止,向前搜索将在缓冲区的末尾停止。如果
'wrapscan' 设置且未找到模式,则会给出错误消息“模式未找到”,并且光标不会移动。如果
'wrapscan' 未设置,则在向前搜索时消息将变为“搜索到达底部但未找到匹配”,在向后搜索时消息将变为“搜索到达顶部但未找到匹配”。如果 wrapscan 设置且搜索环绕文件末尾,则在向后或向前搜索时,分别给出消息“搜索到达顶部,继续从底部开始”或“搜索到达底部,继续从顶部开始”。可以通过在
'shortmess' 选项中设置 's' 标志来关闭此功能。突出显示方法 'w' 用于此消息(默认:突出显示)。
搜索范围 您可以通过包含 \%>l 项来将搜索命令 "/" 限制在一定范围的行内。例如,要匹配第 199 行以下且第 300 行以上的单词“limit”
/\%>199l\%<300llimit
另请参见
/\%>l。
另一种方法是使用带 'c' 标志的 ":substitute" 命令。示例
:.,300s/Pattern//gc
此命令将从光标位置搜索到第 300 行,查找“Pattern”。在匹配时,系统将提示您输入一个字符。输入 'q' 在此匹配处停止,输入 'n' 查找下一个匹配。
"*"、"#"、"g*" 和 "g#" 命令按此顺序查找光标附近的单词,找到第一个匹配的单词即被使用
当前位于光标下的关键字。
光标右侧同一行中的第一个关键字。
当前位于光标下的 WORD。
光标右侧同一行中的第一个 WORD。关键字可能只包含字母和
'iskeyword' 中的字符。WORD 可能包含任何非空白字符(
<Tab>
和/或
<Space>
)。请注意,如果您使用十指打字,字符很容易记住:“#”位于您的左手食指下方(向左向上搜索),“*”位于您的右手食指下方(向右向下搜索)。(这取决于您的键盘布局)。
E956 在极少数情况下,正则表达式被递归使用。这种情况可能发生在执行模式需要很长时间,并且在检查通道上的消息时调用了一个也使用模式的回调或触发了一个自动命令。在大多数情况下,这应该没有问题,但是如果模式在使用时被再次使用,它将失败。通常这意味着模式有问题。
/bar /\bar /pattern 1. 模式是一个或多个分支,由“\|”分隔。它匹配与任何一个分支匹配的任何内容。例如:“foo\|beep”匹配“foo”和“beep”。如果多个分支匹配,则使用第一个分支。
pattern ::= branch or branch \| branch or branch \| branch \| branch etc.
/branch /\& 2. 分支是一个或多个 concat,由“\&”分隔。它匹配最后一个 concat,但只有在所有前面的 concat 也在相同位置匹配时才匹配。例如:“foobeep\&…”匹配“foobeep”中的“foo”。“.*Peter\&.*Bob”匹配包含“Peter”和“Bob”的行的内容。
branch ::= concat or concat \& concat or concat \& concat \& concat etc.
/concat 3. concat 是一个或多个片段的串联。它匹配第一个片段的匹配结果,后面跟着第二个片段的匹配结果,依此类推。例如:“f[0-9]b”,首先匹配“f”,然后是一个数字,然后是“b”。
concat ::= piece or piece piece or piece piece piece etc.
/piece 4. 片段是一个原子,可能后面跟着一个多重匹配,表示原子可以匹配多少次。例如:“a*”匹配任何“a”字符序列:“”、"a"、"aa" 等。参见
/multi。
piece ::= atom or atom multi
/atom 5. 原子可以是长列表中的一个项目。许多原子匹配文本中的一个字符。它通常是一个普通字符或一个字符类。可以使用圆括号将模式变成原子。"\z(\)" 结构仅用于语法高亮。
/\%#= two-engines NFA Vim 包含两个正则表达式引擎:1. 一个旧的、回溯引擎,支持所有内容。2. 一个新的、NFA 引擎,在某些模式上运行得更快,在某些模式上可能运行得更慢。
E1281Vim 将自动为您选择正确的引擎。但是,如果您遇到问题或想要专门选择一个引擎或另一个引擎,您可以在模式前添加以下内容之一
\%#=0 强制自动选择。只有在
'regexpengine' 设置为非零值时才有效。\%#=1 强制使用旧引擎。\%#=2 强制使用 NFA 引擎。
模式中的一些字符,如字母,是按字面意思理解的。它们与文本中完全相同的字符匹配。但是,当在前面加上反斜杠时,这些字符可能具有特殊含义。例如,“a”匹配字母“a”,而“\a”匹配任何字母字符。
其他字符在没有反斜杠的情况下具有特殊含义。它们需要在前面加上反斜杠才能按字面意思匹配。例如,“.”匹配任何字符,而“\.”匹配一个点。
一个字符是按字面意思理解还是不按字面意思理解取决于
'magic' 选项和接下来提到的模式中的项目。
'magic' 选项应该始终设置,但可以关闭以与 Vi 兼容。为了完整性,我们在这里提到了
'nomagic' 的影响,但我们建议不要使用它。
/\m /\M 使用“\m”使它后面的模式被解释为
'magic' 设置,忽略
'magic' 选项的实际值。使用“\M”使它后面的模式被解释为
'nomagic' 使用。
/\v /\V 使用“\v”意味着在它之后,除了 '0'-'9'、'a'-'z'、'A'-'Z' 和 '_' 之外的所有 ASCII 字符都具有特殊含义:“非常神奇”
使用“\V”意味着在它之后,只有反斜杠和终止字符(通常为 / 或 ?)具有特殊含义:“非常不神奇”
示例
之后:\v \m \M \V 匹配
'magic' 'nomagic' a a a a 字面意思的 'a' \a \a \a \a 任何字母字符 . . \. \. 任何字符 \. \. . . 字面意思的点 $ $ $ \$ 行尾 * * \* \* 任意数量的先前原子 ~ ~ \~ \~ 最新的替换字符串 () \(\) \(\) \(\) 将组作为原子 | \| \| \| 无:分隔备选方案 \\ \\ \\ \\ 字面意思的反斜杠 \{ { { { 字面意思的左花括号
如果您愿意,可以通过在模式开头放置“\m”或“\M”来使模式不受
'magic' 选项设置与否的影响。
multi
/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 个或更多,尽可能少
字符类:
/character-classes
magic nomagic matches
/\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 是上面任何一个字符: 包含行尾的字符类 (字符类结束)
x x 没有特殊意义的字符匹配它本身
/[] [] \[] [] 内指定的任何字符
/\%[] \%[] \%[] 一系列可选匹配的原子
/\%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),即使它看起来可能相同。
一个原子可以后面跟着一个指示原子可以匹配多少次以及以何种方式的指示。这被称为多项。参见
/multi 获取概述。
/star /\star * (当
'magic' 未设置时使用 \*) 匹配前一个原子 0 次或多次,尽可能多地匹配。
a* a\* "", "a", "aa", "aaa" 等。 .* \.\* 任何东西,也包括空字符串,没有行尾 \_.* \_.\* 一直到缓冲区结尾的所有内容 \_.*END \_.\*END 一直到缓冲区中最后一个 "END" 的所有内容
例外: 当 "*" 用于模式开头或紧接在 "^" 后面时,它匹配星号字符。
请注意,重复 "\_." 可能匹配大量文本并花费很长时间。例如,"\_.*END" 匹配从当前位置到文件中最后一个 "END" 出现的所有文本。由于 "*" 将匹配尽可能多的内容,因此它首先会跳过所有行,直到文件结尾,然后尝试匹配 "END",每次向后回退一个字符。
/\+ \+ 匹配前一个原子 1 次或多次,尽可能多地匹配。
示例匹配
^.\+$ 任何非空行 \s\+ 至少一个字符的空白
/\= \= 匹配前一个原子 0 次或 1 次,尽可能多地匹配。
示例匹配
foo\= "fo" 和 "foo"
/\? \? 与 \= 相同。在使用 "?" 命令向后搜索时不能使用。
/\{ E60 E554 E870 \{n,m} 匹配前一个原子 n 到 m 次,尽可能多地匹配 \{n} 匹配前一个原子 n 次 \{n,} 匹配前一个原子至少 n 次,尽可能多地匹配 \{,m} 匹配前一个原子 0 到 m 次,尽可能多地匹配 \{} 匹配前一个原子 0 次或多次,尽可能多地匹配 (与 "*" 相同)
/\{-\{-n,m} 匹配前一个原子 n 到 m 次,尽可能少地匹配 \{-n} 匹配前一个原子 n 次 \{-n,} 匹配前一个原子至少 n 次,尽可能少地匹配 \{-,m} 匹配前一个原子 0 到 m 次,尽可能少地匹配 \{-} 匹配前一个原子 0 次或多次,尽可能少地匹配
n 和 m 是正十进制数或零
non-greedy如果 "-" 出现在 "{" 后面,则使用最短匹配优先算法 (参见下面的示例)。特别是,"\{-}" 与 "*" 相同,但使用最短匹配优先算法。但:在相同位置开始的匹配优先于较短的匹配: "a\{-}b" 在 "xaaab" 中匹配 "aaab"。
示例匹配
ab\{2,3}c "abbc" 或 "abbbc" a\{5} "aaaaa" ab\{2,}c "abbc", "abbbc", "abbbbc" 等。 ab\{,3}c "ac", "abc", "abbc" 或 "abbbc" a[bc]\{3}d "abbbd", "abbcd", "acbcd", "acccd" 等。 a\(bc\)\{1,2}d "abcd" 或 "abcbcd" a[bc]\{-}[cd] "abc" 在 "abcd" 中 a[bc]*[cd] "abcd" 在 "abcd" 中
} 可选地用反斜杠开头: \{n,m\}。
/\@= \@= 零宽度匹配前一个原子。在 Perl 中与 "(?=pattern)" 相似。
示例匹配
foo\(bar\)\@= "foo" 在 "foobar" 中 foo\(bar\)\@=foo 没有任何匹配
/zero-width当使用 "\@=" (或 "^", "$", "\<", "\>") 时,没有字符包含在匹配中。这些项仅用于检查是否可以进行匹配。这可能很棘手,因为后续项的匹配将在相同位置进行。上面的最后一个示例将不匹配 "foobarfoo",因为它尝试在 "bar" 匹配的相同位置匹配 "foo"。
请注意,使用 "\&" 与使用 "\@=" 具有相同的效果: "foo\&.." 与 "\(foo\)\@=.." 相同。但是使用 "\&" 更容易,不需要括号。
/\@! \@! 如果前一个原子在当前位置不匹配,则零宽度匹配。
/zero-width 在 Perl 中与 "(?!pattern)" 相似。
示例匹配
foo\(bar\)\@! 任何不以 "bar" 结尾的 "foo" a.\{-}p\@! "a", "ap", "app", "appp" 等。不紧接在 "p" 后面 \(\(then\)\@!.\)*$ "if " 不以 "then" 结尾
使用 "\@!" 比较棘手,因为有很多地方模式不匹配。"a.*p\@!" 将从 "a" 匹配到行尾,因为 ".*" 可以匹配行中的所有字符,并且 "p" 在行尾不匹配。"a.\{-}p\@!" 将匹配任何不以 "p" 结尾的 "a", "ap", "app" 等。,因为 "." 可以匹配 "p",并且 "p\@!" 在那之后不匹配。
你不能使用 "\@!" 来查找匹配位置之前的非匹配项: "\(foo\)\@!bar" 将在 "foobar" 中匹配 "bar",因为在 "bar" 匹配的位置,"foo" 不匹配。为了避免匹配 "foobar",你可以使用 "\(foo\)\@!...bar",但这不匹配一行开头的 "bar"。使用 "\(foo\)\@<!bar"。
有用示例: 在不包含 "bar" 的行中查找 "foo"
/^\%(.*bar\)\@!.*\zsfoo
此模式首先检查行中是否存在 "bar" 匹配的单个位置。如果 ".*bar" 在某个地方匹配,则 \@! 将拒绝模式。当没有匹配项时,任何 "foo" 都将被找到。"\zs" 用于使匹配从 "foo" 之前的某个位置开始。
/\@<= \@<= 如果前一个原子在跟随内容之前匹配,则零宽度匹配。
/zero-width 与 Perl 中的 "(?<=pattern)" 相似,但 Vim 允许使用非固定宽度模式。
示例匹配
\(an\_s\+\)\@<=file "file" 在 "an" 和空白或行尾之后 为了速度,最好避免使用这种多项。尝试使用 "\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" 无法匹配。
一个普通的原子可以是
/^ ^ 在模式开头或 "\|"、"\("、"\%(" 或 "\n" 之后:匹配行首;在其他位置,匹配字面意义上的 '^'。
/zero-width示例匹配
^beep( C 函数 "beep" 的开头(可能)。
/\^ \^ 匹配字面意义上的 '^'。可以在模式中的任何位置使用,但不能在 [] 中使用。
/\_^ \_^ 匹配行首。
/zero-width 可以在模式中的任何位置使用,但不能在 [] 中使用。
示例匹配
\_s*\_^foo 空白和空行,然后在行首使用 "foo"
/\$ \$ 匹配字面意义上的 '$'。可以在模式中的任何位置使用,但不能在 [] 中使用。
/\_$ \_$ 匹配行尾。
/zero-width 可以在模式中的任何位置使用,但不能在 [] 中使用。请注意,"a\_$b" 从不匹配,因为 "b" 无法匹配行尾。请改用 "a\nb"
/\n.
示例匹配
foo\_$\_s* 行尾的 "foo" 以及随后的空白和空行
/\_. \_. 匹配任何单个字符或行尾。注意:"\_.*" 匹配缓冲区中的所有文本,直到结尾!
/\zs \zs 匹配任何位置,但不能在 [] 中使用,并在此处设置匹配的开头:下一个字符是整个匹配的第一个字符。
/zero-width 示例
/^\s*\zsif
匹配行开头的 "if",忽略空格。可以多次使用,在匹配分支中遇到的最后一个将被使用。示例
/\(.\{-}\zsFab\)\{3}
找到 "Fab" 的第三次出现。这不能后跟 multi。
E888
/\ze \ze 匹配任何位置,但不能在 [] 中使用,并在此处设置匹配的结尾:上一个字符是整个匹配的最后一个字符。
/zero-width 可以多次使用,在匹配分支中遇到的最后一个将被使用。例如:"end\ze\(if\|for\)" 匹配 "endif" 和 "endfor" 中的 "end"。这不能后跟 multi。
E888
/\%$ end-of-file \%$ 匹配文件结尾。在与字符串匹配时,匹配字符串结尾。请注意,这不会查找文件中最后一个 "VIM"
/VIM\_.\{-}\%$
它将找到下一个 VIM,因为它后面的部分将始终匹配。这将找到文件中最后一个 "VIM"
/VIM\ze\(\(VIM\)\@!\_.\)*\%$
这使用
/\@! 来确定 "VIM" 在第一个 "VIM" 之后的任何位置都不匹配。从文件结尾向后搜索更容易!
/\%V \%V 匹配 Visual 区域内的内容。当 Visual 模式已停止时,匹配
gv 将重新选择的区域。这是一个
/zero-width 匹配项。为了确保整个模式都在 Visual 区域内,请将其放在模式开头和结尾之前,例如
/\%Vfoo.*ba\%Vr
这在仅 Visual 选择 "foo bar" 时也有效。这
/\%Vfoo.*bar\%V
如果 Visual 选择在 "r" 之后继续,将匹配 "foo bar"。仅适用于当前缓冲区。
/\%# cursor-position \%# 与光标位置匹配。仅在匹配窗口中显示的缓冲区中的内容时有效。
警告:当光标在使用模式后移动时,结果将变为无效。Vim 不会自动更新匹配项。这对于语法高亮和
'hlsearch' 尤其重要。换句话说:当光标移动时,显示不会为此更改而更新。当更改行时(整行更新)或使用
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 \%23l 在特定行中匹配。\%<23l 匹配特定行(较低的行号)上方的部分。\%>23l 匹配特定行(较高的行号)下方的部分。\%.l 在光标所在的行中匹配。\%<.l 匹配光标所在的行上方的部分。\%>.l 匹配光标所在的行下方的部分。这六个可以用于匹配缓冲区中的特定行。"23" 可以是任何行号。第一行是 1。
警告:当插入或删除行时,Vim 不会自动更新匹配项。这意味着语法高亮会很快变得错误。此外,当引用光标位置(".")并且光标移动时,显示不会为此更改而更新。当使用
CTRL-L 命令(整个屏幕更新)时会进行更新。例如,要高亮显示光标当前所在的行
:exe '/\%' .. line(".") .. 'l'
当
'hlsearch' 设置好并且您在周围移动光标并进行更改时,这将清楚地显示匹配项何时更新或未更新。
/\%c /\%>c /\%<c \%23c 在特定列中匹配。\%<23c 匹配特定列之前的部分。\%>23c 匹配特定列之后的部分。\%.c 在光标所在的列中匹配。\%<.c 匹配光标所在的列之前的部分。\%>.c 匹配光标所在的列之后的部分。这六个可以用于匹配缓冲区或字符串中的特定列。"23" 可以是任何列号。第一列是 1。实际上,列是字节数(因此对于多字节字符来说并不完全准确)。
警告:当插入或删除文本时,Vim 不会自动更新匹配项。这意味着语法高亮会很快变得错误。此外,当引用光标位置(".")并且光标移动时,显示不会为此更改而更新。当使用
CTRL-L 命令(整个屏幕更新)时会进行更新。例如,要高亮显示光标当前所在的列
:exe '/\%' .. col(".") .. 'c'
当
'hlsearch' 设置好并且您在周围移动光标并进行更改时,这将清楚地显示匹配项何时更新或未更新。匹配第 44 列中的单个字节的示例
/\%>43c.\%<46c
请注意,当“.”匹配第 44 列中的一个字节时,“\%<46c”在第 45 列中匹配。
/\%v /\%>v /\%<v \%23v 在特定虚拟列中匹配。 \%<23v 在特定虚拟列之前匹配。 \%>23v 在特定虚拟列之后匹配。 \%.v 在当前虚拟列匹配。 \%<.v 在当前虚拟列之前匹配。 \%>.v 在当前虚拟列之后匹配。 这六个可以用来匹配缓冲区或字符串中的特定虚拟列。 当不匹配窗口中的缓冲区时,将使用当前窗口的选项值(例如,
'tabstop')。“23”可以是任何列号。 第一列为 1。 请注意,某些虚拟列位置永远不会匹配,因为它们位于一个占用多个屏幕字符的制表符或其他字符的中间。
警告: 当插入或删除文本时,Vim 不会自动更新突出显示的匹配项。 这意味着语法高亮很快就会变得不正确。 同样,当引用光标位置(“.”)并且光标移动时,显示不会为此更改而更新。 使用
CTRL-L 命令(更新整个屏幕)时,会进行更新。 例如,要突出显示虚拟列 72 之后的所有字符
/\%>72v.*
当
'hlsearch' 设置并且您移动光标并进行更改时,这将清楚地显示匹配项何时更新或未更新。 要匹配到第 17 列的文本
/^.*\%17v
要匹配当前虚拟列(光标所在位置)之后的所有字符
/\%>.v.*
第 17 列不包括在内,因为这是一个
/零宽度 匹配。 要包含该列,请使用
/^.*\%17v.
此命令执行相同的操作,但也匹配第 17 列中没有字符的情况
/^.*\%<18v.
请注意,如果没有“^”来锚定第一列中的匹配项,这也会突出显示第 17 列
/.*\%17v
注意: 以上也适用于多字节字符。 以下仅匹配 ASCII 字符,如范围所示。
空白字符 空白字符 \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
注意: 使用原子比使用 [] 形式更快。
\e 匹配
<Esc>
/\e\t 匹配
<Tab>
/\t\r 匹配
<CR>
/\r\b 匹配
<BS>
/\b\n 匹配行尾
/\n当在字符串而不是缓冲区文本中匹配时,将匹配文字换行符。
\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 将修复它。
“Func” 列显示了使用哪个库函数。实现取决于系统。否则:(1) 对 ASCII 使用 islower(),对其他字符使用 Vim 内置规则。(2) 使用 Vim 内置规则 (3) 与 (1) 相同,但使用 isupper()
/[[= [==]等价类。这意味着匹配的字符具有几乎相同的含义,例如,当忽略重音符时。这仅适用于 Unicode、latin1 和 latin9。形式为:[=a=]
/[[. [..]排序元素。目前仅接受形式为 [.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
注意:上面提到的其他反斜杠代码在 [] 中不起作用!
与集合进行匹配可能很慢,因为文本中的每个字符都需要与集合中的每个字符进行比较。如果可能,请使用上面其他原子之一。例如:"\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]"。
\%d123 匹配使用十进制数字指定的字符。后面必须跟非数字。\%o40 匹配使用八进制数字指定的字符,最多为 0o377。低于 0o40 的数字后面必须跟非八进制数字或非数字。\%x2a 匹配使用最多两个十六进制字符指定的字符。\%u20AC 匹配使用最多四个十六进制字符指定的字符。\%U1234abcd 匹配使用最多八个十六进制字符指定的字符,最多为 0x7fffffff
示例
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
技术细节:
NL-used-for-Nul
文件中存储的
<Nul>
字符在内存中存储为
<NL>
。在显示中,它们显示为 "^@"。转换是在读取和写入文件时完成的。要使用搜索模式匹配
<Nul>
,你只需输入
CTRL-@
或 "CTRL-V 000"。这可能正是你所期望的。在内部,字符在搜索模式中被替换为
<NL>
。不寻常的是,键入
CTRL-V
CTRL-J
也会插入
<NL>
,因此也会在文件中搜索
<Nul>
。
在处理表达式计算时,模式中的 <NL>
字符匹配字符串中的 <NL>
。使用 "\n"(反斜杠 n)匹配 <NL>
在这里不起作用,它只用于匹配缓冲区中的文本。
/\Z 当 "\Z" 出现在模式中的任何位置时,会忽略所有组合字符。因此,只需要匹配基本字符,组合字符可以不同,组合字符的数量也可以不同。例外:如果模式以一个或多个组合字符开头,则必须匹配这些组合字符。
/\%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 被忽略)
在功能方面,Vim 的正则表达式与 Perl 的正则表达式最相似。它们之间的区别主要在于表示法;以下是它们不同的摘要
Vim 中的功能 Perl 中的功能
强制不区分大小写 \c (?i) 强制区分大小写 \C (?-i) 无反向引用的分组 \%(atom\) (?:atom) 保守量词 \{-n,m}
*?,
+?, ??, {}? 0 宽度匹配原子\@= (?=atom) 0 宽度不匹配原子\@! (?!atom) 0 宽度前导匹配原子\@<= (?<=atom) 0 宽度前导不匹配原子\@<! (?<!atom) 不重试匹配原子\@> (?>atom)
Vim 和 Perl 对字符串内的换行符处理方式略有不同
在 Perl 中,^ 和 $ 默认情况下只匹配文本的开头和结尾,但您可以设置 'm' 标志,它允许它们匹配嵌入的换行符。您还可以设置 's' 标志,它会导致 . 也匹配换行符。(顺便说一句,这两个标志都可以在模式内部使用与上面 i 标志相同的语法更改。)
另一方面,Vim 的 ^ 和 $ 始终匹配嵌入的换行符,并且您会得到两个单独的原子,\%^ 和 \$,它们分别只匹配文本的开头和结尾。Vim 通过提供 \_“修饰符”来解决第二个问题:将其放在 . 或字符类前面,它们将匹配换行符。
最后,这些结构是 Perl 独有的
在正则表达式中执行任意代码:(?{perl code})
条件表达式:(?(condition)true-expr|false-expr)
......而这些是 Vim 独有的
更改模式的 magic-ness:\v \V \m \M(对于避免反斜杠itis 非常有用)
可选匹配原子的序列:\%[atoms]
\&(对于 \| 相当于“and”对于“or”;它强制几个分支在一个位置匹配)
按行/列匹配:\%5l \%5c \%5v
设置匹配的开头和结尾:\zs \ze
syntax-vs-match 请注意,匹配突出显示机制独立于
语法突出显示,语法突出显示(通常)是缓冲区本地突出显示,而匹配是窗口本地突出显示,这两种方法可以自由混合。匹配突出显示函数在何时以及如何应用方面为您提供了更多灵活性,但通常仅用于临时突出显示,没有严格的规则。这两种方法都可以用于隐藏文本。
:mat :match :mat[ch]
{group}
/{pattern}/ 在当前窗口中定义要突出显示的模式。它将用
{group}
突出显示。示例
:highlight MyGroup ctermbg=green guibg=green
:match MyGroup /TODO/
除了 // 之外,任何字符都可以用于标记 {pattern}
的开头和结尾。注意使用特殊字符,例如 '"' 和 '|'。
{group}
必须在执行此命令时存在。
请注意,使用
'hlsearch' 突出显示最后一个使用的搜索模式是在所有窗口中使用的,而使用 ":match" 定义的模式只存在于当前窗口中。它在切换到另一个缓冲区时会保留。
当匹配行尾且 Vim 只重新绘制显示的一部分时,您可能会得到意外的结果。这是因为 Vim 会在重新绘制开始的行中查找匹配项。
另一个示例,突出显示虚拟列 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 一样,但设置一个单独的匹配。因此可以同时存在三个匹配项。如果几个匹配项在同一位置,则编号最小的匹配项优先。它使用匹配 ID 3。":3match" 命令由(较旧的 Vim)
matchparen 插件使用。建议您将 ":match" 用于手动匹配,将 ":2match" 用于另一个插件,或者更好地使用更灵活的
matchadd()(以及类似)函数。
模糊匹配是指使用非精确搜索字符串匹配字符串。如果搜索字符串中的所有字符都以相同的顺序出现在字符串中的任何位置,则模糊匹配将匹配字符串。忽略大小写。在匹配的字符串中,其他字符可以出现在搜索字符串中的两个连续字符之间。如果搜索字符串有多个词,则每个词都是单独匹配的。因此,搜索字符串中的词可以在字符串中以任何顺序出现。
模糊匹配根据以下标准为每个匹配字符串分配分数
连续匹配字符的数量。
两个连续匹配字符之间的字符数(距离)。
单词开头的匹配
驼峰式字符的匹配(例如 CamelCase 中的 Case)
路径分隔符或连字符后的匹配。
字符串中不匹配字符的数量。得分最高的匹配字符串将首先返回。
例如,当您使用模糊匹配搜索 "get pat" 字符串时,它将匹配字符串 "GetPattern"、"PatternGet"、"getPattern"、"patGetter"、"getSomePattern"、"MatchpatternGet" 等。
:vimgrep
的 "f" 标志启用模糊匹配。