侧边栏壁纸
博主头像
翻斗

开始一件事最好是昨天,其次是现在

  • 累计撰写 44 篇文章
  • 累计创建 42 个标签
  • 累计收到 3 条评论
VIM

Vim 进阶 - 剪切(删除)、复制、粘贴与寄存器

翻斗
2019-04-25 / 0 评论 / 0 点赞 / 1,269 阅读 / 2,549 字

Vim 和其它编辑器一样,也有剪切、复制、粘贴等操作,但是在 Vim 中这些操作都有不同的名字:删除 delete复制 yank粘贴 put

一般的编辑器在进行复制、剪切等操作时,会使用操作系统的剪贴板 clipboard 来暂时存储文本,而 Vim 的「剪贴板」和系统的剪贴板并不互通,Vim 使用内建的「寄存器 register」来保存文本。

剪切(删除)、复制、粘贴操作

剪切(删除)Delete

在其他编辑器中,剪切一般代表着删除一段文本的同时,将这段文本保存到剪贴板中,以便在其他地方粘贴出来。而在 Vim 当中,剪切和删除并没有明显的界限,因为在 Vim 中,所有被删除的文本都会被放到寄存器中,这样我们在下次想使用的时候可以直接粘贴。

具体放到哪个寄存器里了,以及寄存器的操作方法,我们稍后再说。先来看看 Vim 中和剪切 / 删除相关的命令:

命令 用途
c 删除字符并进入插入模式
cc 删除整行并进入插入模式(=== S)
C 从光标处删除到行尾并进入插入模式
d 删除字符并进入插入模式
dd 删除整行
D 清除当前行的所有字符(不会删除行)
s 删除光标下的字符并进入插入模式
S 删除整行并进入插入模式(=== cc)
x 删除光标下的字符
X 删除光标前面的字符

在 Vim 里,c 代表 change,d 代表 delete

简单来讲,c s 相关的命令在删除字符后会进入插入模式,而 d x 在删除之后会留在普通模式。
cd 可以删除成段字符,而 s x 只删除一个字符。

c{motion}d{motion} 中的{motion} 代表动作命令,例如:
ciw - 删除当前单词并进入插入模式
dt" - 删除到 " 前边
di] - 删除 [] 内包括的内容,等等。

除动作命令外,也可使用可视模式选中文本后用 cd 进行删除。
另外,还有方便的 ccdd 命令可以用来直接删除整行。

复制 Yank

在 Vim 中,yank 代表复制Yank 本来的意思是拉起、拉出。使用 yank 代表复制主要是因为在 Vim 开发的时候 c 已经被 change 占用了,所以只能用还空余的 y 了

y 命令的使用方式和 c、d 类似,y{motion} 可以对复制相应文本,也可以在可视模式下选中文本后用 y 复制。
ccdd 类似,yy 可以复制整行。

粘贴 Put

p 可以把刚刚删除 / 剪切 / 复制的文本放(put)在光标后面。如果是整行的文本,则放在光标下面的行。而 P 是放在前面。

在可视模式下,p 会在粘贴的同时替换选中的文本。

此外,还有 gpgP 命令,和 p P 不同的是,前两个命令会在粘贴之后,把光标的位置移到文本的结尾而不是开头。

寄存器 Register

看到这里,我们已经学到删除 / 剪切 / 复制的一些一本操作,能应付很多日常场景了。
但是设想这样的场景:

我想复制一处的文本 a,并替换另一处的文本 b。我用 y 复制了文本 a,然后把光标移动到文本 b 上,选中或者使用动作命令搭配 d 删除了文本 b,然后按 p。
奇怪的事情发生了,我们得到的并不是文本 a,而是把文本 b 粘贴(put)了出来。糟糕,我把复制的内容弄丢了!

当然你可能会说,复制文本 a 之后,选中文本 b 而不删除,直接用 p 即可完成替换。确实如此,这也是我更倾向的操作,它不会既复制又删除,只用两步操作就完成了替换。

而要弄懂为什么会 put 出文本 b,就要了解寄存器的概念。

什么是寄存器

一般来讲,操作系统的剪贴板只有一个,后来的会覆盖先来的。新的内容被存到剪贴板的同时,老的内容也会被删除。

Vim 的寄存器不太一样,寄存器有很多个,可以通过 {reg}的方式指明要使用的寄存器。其中,"来告诉 Vim,要进行和寄存器有关的操作,而 reg}代表寄存器的名字。
寄存器的名字可以是[a-z0+"*#%.:/]等,其中 [a-z] 共 26 个可供我们随意使用,另外的那些是 Vim 内置的专用寄存器。

使用寄存器

使用"{reg}加命令可以指明我们想要使用的寄存器,例如ds
"ep- 粘贴寄存器 e 中的内容
"fdd 删除当前行并放到 f 寄存器中,等等。

无名寄存器(默认)“”

当没有指定要使用的寄存器时,Vim 会使用无名寄存器 ""
前面提到,c、d、s、x、y 命令都会将相应的文本放到寄存器中,而没有声明 [a-z] 中的某一个时,这段文本就会被放到默认的寄存器 "" 中。而当我们使用 p 进行粘贴的时候,也会读取 "" 中的内容。
这就是糟糕,我把复制的内容弄丢了! 的原因。当我们执行删除操作的时候,删除的文本替换了 “” 中的内容,也就是我们刚刚复制的文本 a。

所以,正如我们刚刚提到的,在 Vim 当中剪切和删除并没有清晰的界限,被删掉的文本也会默认被放到无名寄存器 “” 中,而这有可能会覆盖我们刚刚复制的内容,在使用的时候一定要注意这一点。

当然,我们也可以利用 Vim 的这个特点。例如:
xp 可以删除光标下的字符再把它放到光标后面,也就是交换了光标下面两个字符的位置。
ddp 可以删除当前行,并把这行粘贴在光标下面,也就是交换了光标下面的两行。
有名寄存器 "[a-z]

Vim 提供了完整的 26 个英文字母供我们命名寄存器,这意味着我们可以同时剪切/复制 26 段文本。
使用大写字母命名寄存器,会将相应的内容添加到相对应的小写字母命名的寄存器后面。

复制专用寄存器 "0

当使用 y 进行复制时,复制的文本不仅会被存进无名寄存器 "",也同时会被存进 "0,而 c、d、s、x 均不会覆盖这个寄存器。只有当我们下一次复制的时候,这个寄存器才会被覆盖。
所以,也可以使用这个寄存器来规避糟糕,我把复制的内容弄丢了! 的问题。

系统剪贴板寄存器 "+

前面提到 Vim 使用的寄存器和操作系统的剪贴板是相互隔离的,但是这个隔离也不绝对,使用 "+ 寄存器可以和系统剪贴板进行交互,例如,我们可以通过 "+p 粘贴系统剪贴板的内容,也可以用 "+y 把内容存进系统剪贴板。这意味着我们可以在 Vim 中直接复制文本,然后到其他程序中粘贴。

其他

此外,Vim 还提供了一些其他的寄存器供我们使用,这些寄存器也被称为只读寄存器:

寄存器 内容
"% 当前文件名
"# 轮换文件名
". 上次插入的文本
": 上次执行的命令
"/ 上次查找的模式
0

评论区