Vim中的寄存器:Register

刚接触vim时,相信多多少少都会遇到关于复制粘贴的问题,例如以下两个问题

  1. Vim编辑的内容如何复制到其他地方?
  2. Vim中如何复制(y)一段内容后,多次复用,而不会被替换内容覆盖?

其实这些问题都可能跟Vim中的寄存器有关,寄存器可以想象成内存中存储某些文本的空间,类似于粘贴板。在使用ypd等命令时,都会不经意间的操作Vim的寄存器。

基本用法

Normal模式下,使用"{register}{command}, 例如"add,表示删除当前行内容,并将内容保存至"a寄存器中,而使用"ap,则可以粘贴"a寄存器中的内容。而插入模式下,使用ctrl-r a来表示粘贴"a寄存器中的内容。

Vim中输入:register,会输出使用中的寄存器以及其保存的值,或者:register x指定输出某些寄存器。

寄存器类型

Vim中输入 :help registers,其中介绍了vim中10种类型的寄存器

1
2
3
4
5
6
7
8
9
10
11
There are ten types of registers:		*registers* *{register}* *E354*
1. The unnamed register ""
2. 10 numbered registers "0 to "9
3. The small delete register "-
4. 26 named registers "a to "z or "A to "Z
5. Three read-only registers ":, "., "%
6. Alternate buffer register "#
7. The expression register "=
8. The selection and drop registers "*, "+ and "~
9. The black hole register "_
10. Last search pattern register "/

匿名寄存器

当使用dcsxy等操作时,内容会存储在匿名寄存器""中,如果操作指定寄存器"add,除了"a寄存器,内容也会存入匿名寄存器中。p(aste)默认使用匿名寄存器。

数字寄存器

“0至”9,其中”0会保留最近一次复制的内容,而”1至 “9则会保存最近9次删除操作的内容。当指定拷贝操作的寄存器时,不会写入”0中,但删除操作一定会写入”1中。使用y(ank)命令未指定寄存器时,会将内容保存至”0寄存器,同时””具有相同的内容。

短删除寄存器

顾名思义,对于少于一行的内容操作,除非指定寄存器,否则内容都会被存入 "- 寄存器中。

具名寄存器

通过26个英文字母,指定寄存器,例如”add ,如果原有”a寄存器中含有内容,则会被覆盖,而执行”Add则会在原有内容后追加内容。

只读寄存器

":, "., "%,这三种寄存器读取内容,其中": 表示上次执行的命令行,"% 表示当前编辑文件名,". 表示最近插入的内容。

交替文件寄存器

一般我们会使用ctrl-^来回切换buffer,其中原理则是在"#寄存器中存放交替文件。

表达式寄存器

normal模式下,输入"=,在命令行中输入任何Vim script的表达式,通过使用p(aste),插入表达式结果。

选择拖入寄存器

"*"+ 寄存器, 对于maxOS与windows系统都可以表示为系统粘贴板,而在linux中,会有两种不同的意义,使用"+yy,则可以将vim中的文本,粘贴至其他程序,其他程序复制的内容,也会同步到该寄存器中。而当有文本被拖入Vim中时,文本将会存储在"~寄存器中

黑洞寄存器

"_ 对于所有删除或拷贝到该寄存器的内容,都会消失,从而不会影响其他寄存器;例如删除操作,会影响其他数字寄存器,导致原”9寄存器内容被覆盖,而复制操作,则会改变”0寄存器。

搜索寄存器

normal模式下,通过/{something}搜索,最近一次的关键词会被存放在"/寄存器中。

小结

通过简单了解vim中所有类型的寄存器,大致能解答文章开头的两个问题,也可以实现更多的骚操作。

Vim编辑的内容如何复制到其他地方?

通过”+ 或 “* 寄存器,使用系统粘贴板,当然也可以通过设置

1
set clipboard=unnamed

Vim中如何复制一段内容后,多次复用,而不会被替换内容覆盖?

前文讲到数字寄存器,复制操作时,会保存内容至匿名寄存器以及”0寄存器,而在每次删除操作时,会更新”1-“9寄存器以及匿名寄存器,而p(aste)时,会使用匿名寄存器,所以如果p(aste)操作时,如果有替换内容,匿名寄存器内容会变为替换的内容,不过”0寄存器还是最近一次y(arn)的内容,所以可以使用"0p。或者设置一个map

1
xnoremap p "0p

不过这样会导致 d(elete)操作的内容无法被p(aste)使用,所以只需要使用p(aste)时,替换内容不覆盖匿名寄存器即可。前文有讲到黑洞寄存器"_,不保留不需要的内容,所以我们只需要魔改p(aste)操作,将替换内容删除至黑洞寄存器中,再粘贴内容即可。map如下:

1
xnoremap p "_dP  # 这里因为先删除,所以需要使用大写P

参考

http://einverne.github.io/post/2017/11/vim-registers.html

vim :help registers