---
layout: post
title: "Vim实用技巧进阶(第10章:复制和粘贴) - Practical.Vim.2nd.Edition"
keywords: "vim,practical-vim,copy,paste,register,clipboard,实用技巧"
description: "Practical.Vim.2nd.Edition 实用技巧进阶 第10章:复制和粘贴"
tagline: "Tip 60~64"
date: '2018-11-01 09:44:57 +0800'
category: linux
tags: vim practical-vim linux
---
> {{ page.description }}

# 第10章 复制和粘贴
> Copy and Paste


## Tip 60 匿名寄存器的使用
{: #tip60}
> Delete, Yank, and Put with Vim's Unnamed Register

*Vim* 的 删除, 拷贝, 放置(delete, yank, put) 命令在日常使用中被设计得简单易用. *匿名寄存器* 就是使用频率最高的寄存器

通常, 我们提到的 *剪切*, *拷贝* 和 *粘贴* 都是将文本放在剪贴板上. 

而在 *Vim* 术语中, 我们不说 *剪贴板*, 而是 `寄存器`

#### 互换字符

Keystrokes | Buffer Contents
----       | ----
{start}    | Practica lvi<code class="cursor">m</code>
`F␣`       | Practica<code class="cursor">&nbsp;</code>lvim
`x`        | Practica<code class="cursor">l</code>vim
`p`        | Practical<code class="cursor">&nbsp;</code>vim
{: .table-multi-text}

- `F␣` - 往前搜索 *空格* 字符, 并定位到匹配的位置
- `x` - 删除光标处的 *空格* 字符, 并把删除的字符存入到 *匿名寄存器*
- `p` - 粘贴刚刚删除掉的 *空格*

综合起来: `xp` 这2个命令就相当于把光标处的2个字符互换了位置

#### 互换行

Keystrokes | Buffer Contents
----       | ----
{start}    | <code class="cursor">2</code>) line two <br>1) line one <br>3) line three
`dd`       | <code class="cursor">1</code>) line one <br>3) line three
`p`        | 1) line one <br><code class="cursor">2</code>) line two <br>3) line three
{: .table-multi-text}

- `dd` - 删除光标处的行内容, 并把内容存入到 *匿名寄存器*
- `p` - *vim* 这次知道粘贴的内容是行(line-wise), 所以把 *匿名寄存器* 的内容粘贴到了当前行下面 (注意前面的 `xp` 是粘贴在字符后面)

所以 `ddp` 就相当于当前行和下一行的互换位置

#### 复制行

Keystrokes | Buffer Contents
----       | ----
{start}    | 1) line one <br><code class="cursor">2</code>) line two
`yyp`      | 1) line one <br>2) line two <br><code class="cursor">2</code>) line two
{: .table-multi-text}

`yyp` 和 `ddp` 类似, 都是面向行的; `yyp` 进行了行的复制, 并放到了 *匿名寄存器*, 然后按行的形式粘贴出来, 达到复制行的效果

#### 拷贝撞车

前面 *Vim* 的 *删除*, *拷贝* 和 *放置* 操作看起来都是非常直观的; 那么且看下面的示例

<pre>
collection = getCollection();
process(somethingInTheWay, target);
</pre>

现在我们想将 *somethingInTheWay* 替换为 *collection*, 看看我们如何操作:

Keystrokes | Buffer Contents
----       | ----
`yiw`      | <code class="cursor">c</code>ollection = getCollection();<br> process(somethingInTheWay, target);
`jww`      | collection = getCollection();<br> process(<code class="cursor">s</code>omethingInTheWay, target);
`diw`      | collection = getCollection();<br> process(<code class="cursor">,</code> target);
`P`        | collection = getCollection();<br> process(somethingInTheWa<code class="cursor">y</code>, target);
{: .table-multi-text}

一套操作下来, 跟预想的不一样啊??? 

`yiw` 把 *collection* 存到了 *匿名寄存器* 里, 但是后面的 `diw` 删除 *somethingInTheWay* 的同时, 把 *匿名寄存器* 给覆盖了, 所以粘贴出来却不是我们想要的

为了解决这一问题, 我们需要了解 *vim* 的 *寄存器* 是如何工作的

## Tip 61 寄存器一览
{: #tip61}
> Grok Vim's Registers

*Vim* 不是使用单个剪贴板进行所有剪切, 复制和粘贴(cut, copy, paste)操作, 而是提供多个寄存器. 当我们使用删除, 拉取和放置(delete, yank, put)命令时，我们可以指定我们想要与之交互的寄存器

**Vim 术语差别**: `cut,copy,paste` 和 `delete,yank,put`

<pre>
cut, copy, paste 术语是普片理解的, 并且这些操作可用于大多数桌面软件程序和操作系统.
Vim 也提供这些功能, 但它使用不同的术语: delete, yank, put.

Vim的 put 命令实际上与粘贴操作相同. 
幸运的是, 这两个单词都以字母 <code class="highlighter-rouge">p</code> 开头, 因此可以认为就是粘贴命令了.

Vim 的 yank 命令相当于复制操作.
从历史上看, <code class="highlighter-rouge">c</code>命令已经分配给了更改操作, 因此vi的作者被给出了另一个名称.
<code class="highlighter-rouge">y</code> 键可用, 因此复制操作变为 yank 命令.

Vim 的 delete 命令相当于标准剪切操作.
也就是说, 它将指定的文本复制到寄存器中, 然后将其从文档中删除.

如果想真正的删除文本而不存入寄存器呢? Vim 提供一个特殊的寄存器: 黑洞(black hole).
东西存进去就相当于丢弃了, 黑洞寄存器 寻址符号为:<code class="highlighter-rouge">_</code> 所以真正的删除为: <code class="highlighter-rouge">"_{motion}</code>
</pre>

所以, <span class="red">除非特殊说明, *Vim* 里说的 剪切, 复制, 粘贴操作, 通常上是指 delete, yank, put 操作</span>; 而 *Vim* 里的 剪切 和 复制 是不能在其他程序里进行粘贴的; 后面会介绍特殊的寄存器与剪贴板进行交互, 就可以在其他程序里进行粘贴操作了. 

#### 寄存器访问

语法 `"{register}`

- `"ayiw` - 复制当前的词, 并存到寄存器 *a* 里, 可使用 `"ap` 粘贴出来
- `"bdd` - 删除当前行, 并存到寄存器 *b* 里, 可使用 `"bp` 粘贴出来
- `:delete c` - Ex命令, 删除当前行并存到寄存器 c, 粘贴删除的行可以使用 `:put c`

#### 匿名寄存器(\"\")

匿名寄存器 寻址符号为: `"` 

例如要粘贴命令为:  `""p` 可简写为 `p`

`x`, `s`, `d{motion}`, `c{motion}`, `y{motion}` 等命令(大写亦可)都会把内容另存一份到 *匿名寄存器*; 如果想指定放到某个寄存器里, 可以指定前缀: `"{register}`, 不指定就是默认的 *匿名寄存器*

*匿名寄存器* 的内容很容易被覆盖掉, 所以某些时候要注意一下

#### yank寄存器(\"0)

但使用