Skip to content

Vim 寄存器

寄存器是 Vim 复制、删除、粘贴和宏录制背后的存储系统。普通编辑器通常只有一个剪贴板,Vim 则有多类寄存器:有些自动记录删除历史,有些专门保存 yank 内容,有些连接系统剪贴板,有些还能保存命令和表达式结果。

理解寄存器后,很多“刚复制的内容被删除覆盖了”“怎么粘贴系统剪贴板”“宏为什么能查看和编辑”之类的问题都会变得清楚。

基本用法

寄存器的使用格式是:

text
"寄存器名 + 命令

常见例子:

vim
"ayy      " 复制当前行到寄存器 a
"ap       " 粘贴寄存器 a 的内容
"0p       " 粘贴最近一次 yank 的内容
"+yy      " 复制当前行到系统剪贴板
"+p       " 从系统剪贴板粘贴
:registers " 查看寄存器
:reg a 0 + " 只查看 a、0、+ 寄存器

如果不指定寄存器,Vim 会使用无名寄存器 ""

常见寄存器类型

无名寄存器 ""

无名寄存器保存最近一次 yank、delete 或 change 的内容。最普通的 pP 都从这里粘贴。

vim
yy        " 内容进入 "",也进入 "0
dd        " 内容进入 "",也可能进入数字寄存器
p         " 粘贴 ""

这也是新手最常遇到的问题:先 yy 复制一行,又 dd 删除一行,此时 p 粘贴的是刚删除的行,而不是刚复制的行。解决方法是用 "0p

Yank 寄存器 "0

"0 保存最近一次 yank 的内容。删除和修改通常不会覆盖它。

vim
yy        " 复制到 "" 和 "0
dd        " 覆盖 "",但不覆盖 "0
"0p       " 粘贴刚才 yy 的内容

这是最值得优先掌握的寄存器。

数字寄存器 "1"9

数字寄存器主要保存删除历史,不是“最近 10 次复制”。其中:

  • "1 保存最近一次较大的删除或修改。
  • "2"9 依次保存更早的删除历史。
  • 新的删除会把旧内容向后推。
vim
dd        " 删除整行,内容进入 "1
"1p       " 粘贴最近一次删除
"2p       " 粘贴上一次删除历史

行级删除、跨行删除通常进入数字寄存器。小范围删除还有专门的小删除寄存器。

小删除寄存器 "-

小删除寄存器保存一行以内的小删除,例如 xdwdaw 等。

vim
dw        " 删除一个词,通常进入 "- 和 ""
"-p       " 粘贴小删除寄存器

它的存在能减少小删除对数字删除历史的干扰。

命名寄存器 "a"z

命名寄存器由用户主动使用,适合临时保存多段文本。

vim
"ayy      " 复制当前行到 a
"byap     " 复制当前段落到 b
"ap       " 粘贴 a
"bp       " 粘贴 b

大写寄存器表示追加到对应小写寄存器:

vim
"ayy      " 覆盖 a
"Ayy      " 追加当前行到 a

这在收集多处文本时很有用。

只读寄存器 "."%":

这些寄存器由 Vim 自动维护,通常只读。

vim
".p       " 粘贴最近插入的文本
"%p       " 粘贴当前文件名
":p       " 粘贴最近执行的命令行命令

常见用途是查看状态:

vim
:echo @%
:echo @:

搜索寄存器 "/

搜索寄存器保存最近一次搜索模式。

vim
/error    " 搜索 error,内容进入 "/
:echo @/  " 查看当前搜索模式

也可以手动修改搜索寄存器:

vim
:let @/ = 'TODO'

修改后按 n 会按新的模式继续搜索。

表达式寄存器 "=

表达式寄存器会计算 Vim 表达式,并把结果作为待插入或待粘贴内容。

vim
<C-r>=1+2<CR>        " Insert 模式插入 3
"=strftime('%F')<CR>p " Normal 模式粘贴当前日期

在 Insert 模式中,Ctrl-r 后接寄存器名可以插入寄存器内容。

vim
Ctrl-r a     " 插入寄存器 a
Ctrl-r =     " 插入表达式结果

黑洞寄存器 "_

黑洞寄存器会丢弃内容,适合“不污染剪贴板”的删除。

vim
"_dd      " 删除当前行,但不覆盖 ""
"_x       " 删除字符,但不覆盖 ""

例如你复制了一段内容,想删掉目标位置的一行再粘贴,可以使用:

vim
yy
"_dd
p

系统剪贴板寄存器 "+"*

Vim 与系统剪贴板相关的寄存器有两个:

  • "+:系统剪贴板,通常对应复制/粘贴命令。
  • "*:选择缓冲区,在 X11 环境中通常对应鼠标选中的 primary selection。

常用的是 "+

vim
"+yy      " 复制当前行到系统剪贴板
"+p       " 从系统剪贴板粘贴

是否可用取决于 Vim 是否支持 clipboard:

vim
:version

如果输出中是 +clipboard,说明支持;如果是 -clipboard,需要安装带剪贴板支持的 Vim,或使用终端/Neovim 的其它剪贴板集成方式。

复制、删除、修改对寄存器的影响

Yank

y 会写入无名寄存器和 "0

vim
yiw       " 复制当前单词到 "" 和 "0
yap       " 复制当前段落到 "" 和 "0

如果指定命名寄存器,则同时写入该寄存器:

vim
"ayi"     " 复制引号内文本到 a

Delete

d 会写入无名寄存器。较大的删除还会写入数字寄存器,小删除会写入 "-

vim
dd        " 写入 "" 和 "1
dw        " 写入 "" 和 "-

Change

c 本质上也是先删除再进入 Insert 模式,因此也会影响寄存器。

vim
ciw       " 当前单词进入相关寄存器,然后进入 Insert 模式

如果只是想替换文本但保留无名寄存器,可以配合黑洞寄存器:

vim
"_ciw

宏也是寄存器

宏录制使用命名寄存器保存按键序列。

vim
qa        " 开始录制宏到寄存器 a
q         " 停止录制
@a        " 执行宏 a
@@        " 重复上一次宏
10@a      " 执行宏 a 十次

因为宏存在寄存器里,所以可以查看:

vim
:reg a
:echo @a

也可以编辑宏。常见做法是把宏粘贴到缓冲区,修改后再 yank 回寄存器。

vim
"ap       " 粘贴宏内容
"ayy      " 修改后复制回 a

宏适合处理“结构重复但每行内容不同”的编辑,例如批量给多行添加字段、转换列表格式、重复执行搜索后修改。

常见场景

保留刚复制的内容

vim
yiw       " 复制当前单词
dw        " 删除另一个词,覆盖了 ""
"0p       " 仍然粘贴刚才 yank 的词

删除但不影响粘贴

vim
yy        " 复制一行
"_dd      " 删除目标行但不覆盖 ""
p         " 粘贴复制的行

收集多行到同一个寄存器

vim
"ayy      " 先放入 a
"Ayy      " 追加到 a
"Ayy      " 继续追加
"ap       " 一次性粘贴

在 Insert 模式插入文件名

vim
Ctrl-r %

把搜索词替换成寄存器内容

如果寄存器 a 里有替换文本:

vim
:%s/foo/\=@a/g

这里 \= 表示替换部分使用表达式求值。

排错

  • p 粘贴的不是刚复制的内容:试试 "0p
  • 删除覆盖了剪贴板:删除时用 "_d"_dd
  • "+p 无效:检查 :version 是否有 +clipboard
  • 宏执行结果异常:用 :reg a 查看宏内容,确认是否录入了多余按键。
  • 命名寄存器内容消失:小写写入会覆盖,大写写入才是追加。

寄存器看起来复杂,但日常最重要的是四个:"""0"_"+。先掌握它们,再逐步使用命名寄存器和宏。

别急,先让缓存热一下。