我们写代码或者文档时,经常需要在多行的行首或者行尾添加同样的内容,手动一行行操作显然效率很低,做这样的事情有方便的技巧。
案例一
把
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,+4
、5,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;
如果想让它和注释功能都能用,就得想办法动态修改配置了,可以映射到按键或者命令上。
但一般来说在行尾添加内容的操作并不常见,直接用命令即可。