Learn Vim 第十二章:搜索和替换

本文翻译自 iggredible/Learn-Vim,部分内容有增改。

本章涵盖两个独立但相关的概念:搜索和替代。很多时候,您得基于文本的共同模式搜索大量的内容。通过学习如何在搜索和替换中使用正则表达式而不是字面字符串,您将能够快速定位任何文本。

附带说明一下,在本章中,当谈论搜索时,我将主要使用/。您使用/进行的所有操作也可以使用?完成。

智能区分大小写

尝试匹配搜索词的大小写可能会很棘手。如果要搜索文本”Learn Vim”,则很容易把字母的大小写输错,从而得到错误的搜索结果。如果可以匹配任何情况,会不会更轻松,更安全?这是选项ignorecase闪亮的地方。只需在 vimrc 中添加set ignorecase,所有搜索词就不区分大小写。

但是,有时您需要搜索特定大小写的短语。为避免反复开关ignorecase选项,Vim 有一个smartcase选项。您可以将ignorecase和smartcase选项结合起来,当您输入的搜索词全部是小写时,进行大小写不敏感搜索;而当搜索词 至少有1个大写字母时,进行大小写敏感搜索。

在您的 vimrc 中,添加:

set ignorecase smartcase

如果您有这些文字:

hello
HELLO
Hello
  • /hello 匹配”hello”,”HELLO”和”Hello”。
  • /HELLO 仅匹配”HELLO”。
  • /Hello 仅匹配”Hello”。

有一个缺点。如果只需要搜索小写字符串怎么办?您可以在搜索词前使用\C模式来告诉 Vim,后续搜索词将区分大小写。如果执行/\Chello,它将严格匹配”hello”,而不是”HELLO”或”Hello”。

一行中的第一个和最后一个字符

您可以使用^匹配行中的第一个字符,并使用$匹配行中的最后一个字符。

如果您有以下文字:

hello hello

您可以使用/^hello来定位第一个”hello”。要定位最后一个”hello”,请运行/hello$。

如果您有以下文字:

hello hello friend

运行/hello$将匹配不到任何内容,因为”friend”是该行的最后一项,而不是”hello”。

重复搜索

您可以使用//重复上一个搜索。如果您只是搜索/hello,则运行//等同于运行/hello。另外,回想一下前面的章节,您还可以使用n和N分别以相同方向和相反方向重复上一次搜索。

如果您想快速回忆起第n个最近使用的搜索字怎么办?您可以先按/,然后按up/down方向键(或Ctrl-N/Ctrl-P),快速遍历搜索历史,直到找到所需的搜索词。要查看所有搜索历史,可以运行:history /。

在搜索过程中到达文件末尾时,Vim 会抛出一个错误。您可以使用set wrapscan选项使 Vim 在到达文件末尾时回到文件顶部进行搜索。

使用候选词搜索

一次搜索多个单词属于日常操作。如果您需要搜索”hello vim”或”hola vim”,则可以使用|或运算符。

给予这样一段文本:

hello vim
hola vim
salve vim
bonjour vim

如果您不想每次都输入\|,则可以在搜索开始时使用magic语法(\v):/\vhello|hola。有了\v,您就不必再转义特殊字符了。

设置模式匹配的开始位置和结束位置

也许您需要搜索的文本是复合词的一部分。如果您有这些文字:

11vim22
vim22
11vim
vim

如果您仅需要选择以”11”开始、以”22”结束的”vim”,您可以使用\zs(开始匹配)和\ze(结束匹配)运算符。 执行:

/11\zsvim\ze22

Vim仍然会匹配整个模式”11vim22”,但是仅高亮显示介于\zs和\ze之间的内容。

搜索字符组

最基本的模式是字符组[ ]。

如果您需要搜索任何数字,可以使用/[0-9]来匹配一位数字。/[a-z]来搜索小写字母,/[A-Z]来搜索大写字母。

您可以将这些范围组合在一起。如果您需要搜索数字 0-9 以及从 a 到 f(十六进制)的小写字母和大写字母,可以执行/[0-9a-fA-F]。

要进行否定搜索,可以在字符范围括号内添加^。要搜索非数字,请运行/[^0-9]。

搜索重复字符

您可以将count传递给您的搜索。它具有以下语法:

{n,m}

这些count周围的花括号需要被转义。这是count语法的四种不同变体:

  • {n}是精确匹配。 /[0-9]\{2\}匹配两个数字。
  • {n,m}是范围匹配。 /[0-9]\{2,3\}匹配 2 到 3 位数字。
  • {,m}是上限匹配。 /[0-9]\{,3\}匹配最多 3 个数字。
  • {n,}是下限匹配。 /[0-9]\{2,\}匹配最少 2 个或多个数字。

计数参数\{0,\}(零或多个)和\{1,\}(一个或多个)是最常见的搜索模式,Vim 为它们提供了特殊的操作符:*和+。

预定义的字符组

Vim 为常见字符组提供了简写:

\d    数字[0-9]
\D    非数字[^0-9]
\s    空格字符(空格和制表符)
\S    非空白字符
\w    单词字符[0-9A-Za-z_]
\l    小写字母[a-z]
\u    大写字符[A-Z]

搜索示例:在一对相似字符之间捕获文本

如果要搜索由双引号引起来的短语:

"Vim is awesome!"

运行这个:

/"[^"]\+"

这是一个通用模式用于捕获 由一对类似的定界符包围的短语。

搜索示例:捕获电话号码

如果要匹配以连字符(-)分隔的美国电话号码,例如123-456-7890,则可以使用:

/\v\d{3}-\d{3}-\d{4}

基本替换

Vim 的替代命令语法为:

:s/{old-pattern}/{new-pattern}/

替换范围

:[range]s/old/new/
  • :,3s/let/const/ - 从当前行替换到第 3 行。
  • :1,s/let/const/ - 从第 1 行替换到当前行。
  • :3s/let/const/ - 仅在第3行进行替换。
  • :%s/let/const/ - 在所有行上进行替换。

模式匹配

要交换”let”和变量名位置:

:%s/\v(\w+) (\w+)/\2 \1/

\1, \2, \3等代表捕获的分组。

替换标志

g    替换行中的所有匹配项。
c    要求替代确认。
e    防止替换失败时显示错误消息。
i    执行不区分大小写的替换
I    执行区分大小写的替换

特殊替换

\U    将后面跟着的字符变为大写
\u    将后面跟着的第一个字符变为大写
\L    将后面跟着的字符变为小写
\l    将后面跟着的第一个字符变为小写

贪婪与非贪婪

*表示贪婪匹配,而{-}表示非贪婪匹配。

:s/a.*1/\U&/g     " 贪婪模式,得到 ABC1DE1
:s/a.\{-}1/\U&/g  " 非贪婪模式,得到 ABC1de1

跨多个文件替换

:args *.txt
:argdo %s/dog/chicken/
:argdo update

用宏跨多个文件替换

:args *.txt
qq
:%s/dog/chicken/g
:wnext
q
99@q

以聪明的方式学习搜索和替换

良好的搜索能力是编辑的必要技能。掌握搜索功能使您可以利用正则表达式的灵活性来搜索文件中的任何模式。花些时间学习这些。要想掌握正则表达式,您必须在实践中去不断地使用它。