vim 的搜索和替换

原文地址:https://linuxize.com/post/vim-find-replace/

这篇文章描述了如何在 Vim/Vi 中查找和替换文本。

Vim 是最流行的命令行文本编辑器,它在 macOS 和很多 Linux 发行版系统中是预装的软件。在 Vim 中查找和替换文本是比较快速而且容易的。

基本的查找和替换

在 Vim 中,你可以使用 :substitute 命令进行查找和替换。

为了在 Vim 中执行这个指令,你必须使 Vim 处于 normal 模式——即启动 Vim 编辑器时的默认模式。你可以按 'Esc' 键来从其他任何模式返回到 normal 模式。

替换命令的通用格式如下:

:[range]s/{pattern}/{string}/[flags] [count]

这个命令在 [range] 中的每一行中查找一个 {pattern},然后使用一个 {string} 来替换它。[count] 是一个乘以此命令的正整数。

如果没有提供 [range][count],那么,只有在当前行中查找到第一个的 pattern 会被替换掉。当前行是指光标所在的那一行。

举个例子,来搜索当前行中第一次出现的字符串 'foo' 然后用 'bar' 来替换它,你可以使用

:s/foo/bar/

如果想替换调当前行中所有的被匹配的 pattern,你需要加上一个 g 标志:

:s/foo/bar/g

如果你想在整个文件中搜索和替换 pattern,那么可以使用百分号的符号 % 来作为 range。这个符号表示的范围是从第一行到最后一行:

:%s/foo/bar/g

如果省略 {string} 部分 ,那么,此部分将会被认为是一个空字符串,然后,被匹配的 pattern 就会被删除掉。下面的命令删除了当前行中所有的 'foo' 字符串:

:s/foo/g

/ 在除了作为分隔符之外,你还可以使用其他任何非字母和数字的单字节符号来代替斜线符号 /。这个选项在我们的需要搜索的 pattern 中或者替换字符串中含有 / 符号的时候是很有用的。

:s|foo|bar|

按:实测,使用 | 作为分隔符可以替换,但是替换完之后会报错,但是,像 ? 之类的符号作为分隔符就完全没有问题。

如果要手动确认每一个替换,使用 c 标志:

:s/foo/bar/gc

output:

replace with bar (y/n/a/q/l/^E/^Y)?

y 来替换匹配到的结果,或者按 l 来替换匹配到的结果并退出。

n 来跳过当前的匹配结果,然后按 qEsc 来退出替换模式。

a 选项是替换当前的匹配到的结果并且替换掉所有剩下的匹配的结果。向下滚动屏幕,使用 CTRL + Y,向上滚动,使用 CTRL + E

你也可以使用正则表达式来作为一个搜索 pattern。下面的命令会用 'Vim is the best' 替换掉所有以 'foo' 开头的行。

:%s/^foo.*/Vim is the best/gc

^ 符号匹配一行的开头,.* 匹配任何数字或者字符串。

大小写敏感

默认情况下,搜索操作时大小写敏感的;搜索 "FOO" 将不会匹配 "Foo"

为了让搜索 pattern 忽略大小写,可以使用 i 标志:

:s/Foo/bar/gi

另外一个强制忽略大小写的方法是在搜索 pattern 后面添加 \c。举个例子,/Linux\c 就是一个忽略大小写的搜索。

如果你改变了默认的大小写敏感设置(比如在 Vim 的配置文件中),然后你想在搜索中使用大小写敏感的方式,可以使用 I 标志:

:s/foo/bar/gI

类似的,在 pattern 后面加上 \C 也可以强制大小写敏感。

搜索范围

当在命令中没有给出 range 时,那么,替换命令只会操作当前行。

这个 range 既可以是一行也可以是两行之间。具体的 line 值使用 , 或者 ; 来分隔。这个 range 可以使用绝对的行号或者一些特殊的符号来具体化。

举个例子,来替换第 3 行到第 10 行之间的所有的 'foo''bar',可以使用:

:3,10s/foo/bar/g

这个范围是闭区间,也就是说,第一行和最后一行也被包括在 range 中。

. 符号表示当前行,美元符号 $ 表示最后一行。来替换从当前行到最后一行的 'foo''bar',可以使用:

:.,$/foo/bar/g

按:原文中没有加 g

我们也可以使用 + 或者 - 符号来设置具体的行,它的后面跟着具体的数字,这个数字将被当前行数字给加上或者减去。如果 +- 后面的数字被省略,那么,该数字将默认被设置成 1。

举例,从当前行到接下来的四行(一共是 5 行)中替换每一个 'each''bar',可以使用:

:.,+4s/foo/bar/g

替换整个单词

substitute 命令是以字符串的形式来寻找 pattern 的,而不是一整个单词。如果,举例来说,你想要搜索 "gnu",那么将会搜索到在更长的单词中所包含的 "gnu",比如 "cygnus""magnum"

想要搜索一整个单词,键入 \< 来标记一个单词的开始,然后输入搜索的 pattern,然后键入 \> 来标记单词的结尾。

举例来说,要搜索单词 "foo",你可以使用 \<foo\>

:s/\<foo\>/bar/

替换历史

Vim 会跟踪你在当前会话中运行的所有命令。要浏览先前替代命令的历史记录,请输入 :s 并使用向上/向下箭头键查找先前的替换操作。要运行该命令,只需按 Enter。您也可以在执行操作之前编辑命令。

例子

替换从 20 行开始的 3 行(20, 21, 22)中的每一行中的第一个 'foo''bar'

:20,20s/foo/bar/ 3

替换文件中每一行的第一个 'foo''bar'

:%s/foo/bar/

注释 5 到 20 行:

:5,20s/^/#/

取消 5 到 20 行的注释,恢复先前的更改:

:5,20s/^#//

'apple''orange',和 'mango' 替换成 'fruit'

:%s/apple\|orange\|mango/fruit/g

删除每行末尾的尾随空格:

:%s/\s\+$//e

按:

这里似乎不应该用 e,虽然用了也没什么影响。而 e 似乎只有在使用 / 搜索字符串时才有用。

关于 e 标志,有如下解释:

Where you land

Searches in Vim put the cursor on the first character of the matched string by default; if you search for Debian, it would put the cursor on the D. That’s usually fine, but Vim has a few options for offsetting the cursor placement from the beginning of the matched string.

To land on the last character in the matched string, rather than the beginning, add an /e to your search:

/Debian/e

That will place the cursor on the n rather than the D. Vim also allows you to specify a cursor offset by line, or from the beginning or end of the string. To have the cursor land two lines above a matched string, for example, use /string/-2. To place the cursor two lines below the string, use /string/+2.

To offset from the beginning of the string, add a /b or /s with the offset that you want. For example, to move three characters from the beginning of the search, you’d use /string/s+3 or /string/b+3 — “s” for “start” or “b” for “begin.” To count from the end of the string, use /e instead, so /string/e-3 will place the cursor on the third character from the last character of the matched string.

来源:https://www.linux.com/training-tutorials/vim-tips-basics-search-and-replace/

给 38 到 42 行加注释:

:38,42s/p/# /

总结

搜索和替换是 Vim 的一个很强大的功能,它可以使你快速对你的文本做出改变。


vim 的搜索和替换
http://fanyfull.github.io/2021/11/28/vim-的搜索和替换/
作者
Fany Full
发布于
2021年11月28日
许可协议