我们写代码或者文档时,经常需要在多行的行首或者行尾添加同样的内容,手动一行行操作显然效率很低,做这样的事情有方便的技巧。

案例一

aaa
bbb
ccc

ddd
eee

改成

# aaa
# bbb
# ccc
# 
# ddd
# eee

注释掉一段代码是非常常用的操作,很多人都知道如何操作,直接替换即可:

:%s/^/# 

# 后有一个空格。^ 只匹配行首的位置,而不匹配任何字符,所以可以直接替换,$ 也同理。

另外也可以用列选择模式(<C-v>,也可以用 <C-q>,因为 <C-v> 通常用于粘贴,可以在 Vim 或者终端中把 <C-v> 映射为粘贴功能,这样和其他软件一致会方便不少),选定这些行,然后 I# <Esc> 但这样想跳过空行就不大方便了,所以不展开了。

案例二

很多人不喜欢在空行的行首添加注释(尤其不想在行尾添加一个空格),所以需要把

aaa
bbb
ccc

ddd
eee

改成

# aaa
# bbb
# ccc

# ddd
# eee

先全部替换再删除效率肯定低下,可以这样:

:%s/./# &

重点是对 & 的使用,它代表前边匹配到的内容(也就是非空行的第一个字符)。

案例三

实际场景我们很少整体注释掉一个文件,一般都是注释其中的某一段,比如把

aaa
bbb
ccc

ddd
eee

fff
ggg

hhh
iii

改成

aaa
bbb
ccc

# ddd
# eee

# fff
# ggg

hhh
iii

这次操作是从第 5 行开始,下次操作可能就从 193 行开始了,用 5G 定位后再操作肯定不通用也不方便,用搜索定位通常会方便很多:

:/ddd/,/ggg/s/./# &

:/ddd/,/ggg/ 就是让后边的操作只作用于 ddd 和 ggg 之间。

有时我们只需要用搜索定位到起始行,然后注释掉后边确定的几行(在这里注释当前行和后边的 4 行),可以这样:

:/ddd/,+4s/./# &

+4 的意思是把之后的 4 行也放到作用范围内。如果直接用行号,改成行号就行,比如 5,+45,9。如果想先选定再操作,定位到起始行,然后 V,再定位到结束行,再输入 :s/./# & 就可以,都是常规操作,不赘述。

案例四

有时我们要在行尾添加内容,比如添加一个分号,把:

aaa
bbb
ccc

ddd
eee

改成

aaa;
bbb;
ccc;

ddd;
eee;

那可以用:

:%s/.$/&;

这回 . 匹配到的是非空行的最后一个字符,如法炮制即可。定位范围和上边几个案例的操作一样。

绑定到按键

如果自己经常需要这类操作,每次都输入命令还是比较麻烦的,可以绑定到按键,比如:

nnoremap <Leader>c :s/./# &<CR>
vnoremap <Leader>c :s/./# &<CR>

<Ldader> 默认是 \,不大好按,很多人把它映射到了 , 上:

let mapleader = ','
nnoremap \ ,

会方便不少,可以试试。

这样虽然简单,但通用性不强,比如不同的代码注释方法不同,每种注释方法都映射到按键显然太浪费了,也不方便。可以使用现有插件。

使用 vim-commentary 插件

注释掉一段代码是很常见的操作,已经有人写好了插件,可以直接使用。

https://github.com/tpope/vim-commentary

安装后,gc 就是注释(或取消注释)操作,比如 gcc 是修改当前行,gcG 是从当前行修改到文件末尾。插件会识别常见的编程语言或者配置文件,也可以添加自定义格式。需要注意的是它会全部使用行注释,不会使用块注释,比如 C 代码会被注释成这样:

/* int main() { */

/*     return 0; */
/* } */

选上再敲一次 gc 就会取消注释,所以并不影响使用。如果想用块注释,其实就没必要用插件了,因为只需要操作两行。

看起来这个插件不支持在行尾添加内容,其实可以通过自定义配置搞定,比如:

autocmd FileType xxx setlocal commentstring=%s;

如果想让它和注释功能都能用,就得想办法动态修改配置了,可以映射到按键或者命令上。

但一般来说在行尾添加内容的操作并不常见,直接用命令即可。

文章目录