Linux Vim 寄存器 | 从基础分类到高级应用

发布于:2025-03-20 ⋅ 阅读:(18) ⋅ 点赞:(0)

注:本文为 “vim 寄存器” 相关文章合辑

英文引文,机翻未校。

中文引文,略作重排。

未整理去重,如有内容异常,请看原文。


Registers

寄存器

Learning Vim registers is like learning algebra for the first time. You didn’t think you need it until you needed it.
学习 Vim 寄存器就像第一次学习代数一样。直到需要时,你才会意识到它的必要性。

You’ve probably used Vim registers when you yanked or deleted a text then pasted it with p or P. However, did you know that Vim has 10 different types of registers? Used correctly, Vim registers can save you from repetitive typing.
你可能在使用 pP 粘贴文本时已经用过 Vim 寄存器了。但你可能不知道,Vim 有 10 种不同类型的寄存器。如果使用得当,Vim 寄存器可以帮你避免重复输入。

In this chapter, I will go over all Vim register types and how to use them efficiently.
在本章中,我将介绍所有类型的 Vim 寄存器及其高效使用方法。

The Ten Register Types

十种寄存器类型

Here are the 10 Vim register types:
以下是 10 种 Vim 寄存器类型:

序号 英文描述 中文描述
1 The unnamed register (""). 无名寄存器 ("")。
2 The numbered registers ("0-9). 编号寄存器 ("0-9)。
3 The small delete register ("-). 小删除寄存器 ("-)。
4 The named registers ("a-z). 命名寄存器 ("a-z)。
5 The read-only registers (":, "., and "%). 只读寄存器 (":, "., "%)。
6 The alternate file register ("#). 备用文件寄存器 ("#)。
7 The expression register ("=). 表达式寄存器 ("=).
8 The selection registers ("* and "+). 选择寄存器 ("*"+)。
9 The black hole register ("_). 黑洞寄存器 ("_)。
10 The last search pattern register ("/). 最后搜索模式寄存器 ("/)。

Register Operators

寄存器操作符

To use registers, you need to first store them with operators. Here are some operators that store values to registers:
要使用寄存器,你需要先用操作符将值存储到寄存器中。以下是一些可以将值存储到寄存器的操作符:

y Yank (copy) // 拉取(复制)
c Delete text and start insert mode // 删除文本并进入插入模式
d Delete text // 删除文本

There are more operators (like s or x), but the above are the useful ones. The rule of thumb is, if an operator can remove a text, it probably stores the text to registers.
还有更多操作符(如 sx),但上面这些是比较有用的。一般来说,如果一个操作符可以删除文本,它很可能会将文本存储到寄存器中。

To paste a text from registers, you can use:
要从寄存器中粘贴文本,可以使用:

p Paste the text after the cursor // 在光标后粘贴文本
P Paste the text before the cursor // 在光标前粘贴文本

Both p and P accept a count and a register symbol as arguments. For example, to paste ten times, do 10p. To paste the text from register a, do "ap. To paste the text from register a ten times, do 10"ap. By the way, the p actually technically stands for “put”, not “paste”, but I figure paste is a more conventional word.
pP 都接受计数和寄存器符号作为参数。例如,要粘贴十次,可以执行 10p。要粘贴寄存器 a 中的文本,可以执行 "ap。要将寄存器 a 中的文本粘贴十次,可以执行 10"ap。顺便说一下,p 实际上技术上代表的是 “put”,而不是 “paste”,但我认为 “paste” 是一个更常用的词。

The general syntax to get the content from a specific register is "a, where a is the register symbol.
从特定寄存器中获取内容的通用语法是 "a,其中 a 是寄存器符号。

Calling Registers From Insert Mode

从插入模式调用寄存器

Everything you learn in this chapter can also be executed in insert mode. To get the text from register a, normally you do "ap. But if you are in insert mode, run Ctrl-R a. The syntax to call registers from insert mode is:
你在本章学到的所有内容都可以在插入模式中执行。通常,要获取寄存器 a 中的文本,可以执行 "ap。但如果处于插入模式,可以运行 Ctrl-R a。从插入模式调用寄存器的语法是:

Ctrl-R a

Where a is the register symbol. Now that you know how to store and retrieve registers, let’s dive in!
其中 a 是寄存器符号。现在你已经知道了如何存储和检索寄存器,让我们继续深入!

The Unnamed Register

无名寄存器

To get the text from the unnamed register, do ""p. It stores the last text you yanked, changed, or deleted. If you do another yank, change, or delete, Vim will automatically replace the old text. The unnamed register is like a computer’s standard copy / paste operation.
要从无名寄存器中获取文本,可以执行 ""p。它存储了你最后一次拉取、更改或删除的文本。如果你再次执行拉取、更改或删除操作,Vim 会自动替换旧文本。无名寄存器就像计算机的标准复制/粘贴操作一样。

By default, p (or P) is connected to the unnamed register (from now on I will refer to the unnamed register with p instead of ""p).
默认情况下,p(或 P)连接到无名寄存器(从现在开始,我将用 p 代替 ""p 来指代无名寄存器)。

The Numbered Registers

编号寄存器

Numbered registers automatically fill themselves up in ascending order. There are 2 different numbered registers: the yanked register (0) and the numbered registers (1-9). Let’s discuss the yanked register first.
编号寄存器会自动按升序填充。编号寄存器有两种:拉取寄存器 (0) 和编号寄存器 (1-9)。我们先来讨论拉取寄存器。

The Yanked Register

拉取寄存器

If you yank an entire line of text (yy), Vim actually saves that text in two registers:
如果你拉取了一整行文本(yy),Vim 实际上会将该文本保存到两个寄存器中:

  1. The unnamed register (p).
    无名寄存器 (p)

  2. The yanked register ("0p).
    拉取寄存器 ("0p)

When you yank a different text, Vim will update both the yanked register and the unnamed register. Any other operations (like delete) will not be stored in register 0. This can be used to your advantage, because unless you do another yank, the yanked text will always be there, no matter how many changes and deletions you do.
当你拉取不同的文本时,Vim 会同时更新拉取寄存器和无名寄存器。其他操作(如删除)不会存储到寄存器 0 中。你可以利用这一点,因为除非你再次执行拉取操作,否则拉取的文本将始终存在,无论你进行了多少次更改和删除操作。

For example, if you:
例如,如果你:

  1. Yank a line (yy)
    拉取一行(yy

  2. Delete a line (dd)
    删除一行(dd

  3. Delete another line (dd)
    再删除一行(dd

The yanked register will have the text from step one.
拉取寄存器将包含第一步中的文本。

If you:
如果你:

  1. Yank a line (yy)
    拉取一行(yy

  2. Delete a line (dd)
    删除一行(dd

  3. Yank another line (yy)
    再拉取一行(yy

The yanked register will have the text from step three.
拉取寄存器将包含第三步中的文本。

One last tip, while in insert mode, you can quickly paste the text you just yanked using Ctrl-R 0.
还有一个小提示,在插入模式下,你可以使用 Ctrl-R 0 快速粘贴刚刚拉取的文本。

The Non-zero Numbered Registers

非零编号寄存器

When you change or delete a text that is at least one line long, that text will be stored in the numbered registers 1-9 sorted by the most recent.
当你更改或删除至少有一行长的文本时,该文本将按最近使用顺序存储在编号寄存器 1-9 中。

For example, if you have these lines:
例如,如果你有以下几行:

line three
line two
line one

With your cursor on “line three”, delete them one by one with dd. Once all lines are deleted, register 1 should contain “line one” (most recent), register two “line two” (second most recent), and register three “line three” (oldest). To get the content from register one, do "1p.
将光标放在 “line three” 上,然后逐行使用 dd 删除它们。删除所有行后,寄存器 1 应该包含 “line one”(最近的),寄存器 2 包含 “line two”(第二近的),寄存器 3 包含 “line three”(最老的)。要从寄存器 1 中获取内容,可以执行 "1p

As a side note, these numbered registers are automatically incremented when using the dot command. If your numbered register one ("1) contains “line one”, register two ("2) “line two”, and register three ("3) “line three”, you can paste them sequentially with this trick:
顺便说一下,使用点命令时,这些编号寄存器会自动递增。如果编号寄存器 1("1)包含 “line one”,寄存器 2("2)包含 “line two”,寄存器 3("3)包含 “line three”,你可以使用以下技巧依次粘贴它们:

  • Do "1P to paste the content from the numbered register one ("1).
    执行 "1P 粘贴编号寄存器 1("1)中的内容

  • Do . to paste the content from the numbered register two ("2).
    执行 . 粘贴编号寄存器 2("2)中的内容

  • Do . to paste the content from the numbered register three ("3).
    执行 . 粘贴编号寄存器 3("3)中的内容

This trick works with any numbered register. If you started with "5P, . would do "6P, . again would do "7P, and so on.
这个技巧适用于任何编号寄存器。如果你从 "5P 开始,. 将执行 "6P,再次执行 . 将执行 "7P,依此类推。

Small deletions like a word deletion (dw) or word change (cw) do not get stored in the numbered registers. They are stored in the small delete register ("-), which I will discuss next.
小的删除操作,如删除单词(dw)或更改单词(cw),不会存储在编号寄存器中。它们会存储在小删除寄存器("-)中,接下来我会讨论它。

The Small Delete Register

小删除寄存器

Changes or deletions less than one line are not stored in the numbered registers 0-9, but in the small delete register ("-).
小于一行的更改或删除不会存储在编号寄存器 0-9 中,而是存储在小删除寄存器("-)中。

For example:
例如:

  1. Delete a word (diw)
    删除一个单词(diw

  2. Delete a line (dd)
    删除一行(dd

  3. Delete a line (dd)
    再删除一行(dd

"-p gives you the deleted word from step one.
"-p 会给出第一步中删除的单词

Another example:
另一个例子:

  1. I delete a word (diw)
    我删除了一个单词(diw

  2. I delete a line (dd)
    我删除了一行(dd

  3. I delete a word (diw)
    我又删除了一个单词(diw

"-p gives you the deleted word from step three. "1p gives you the deleted line from step two. Unfortunately, there is no way to retrieve the deleted word from step one because the small delete register only stores one item. However, if you want to preserve the text from step one, you can do it with the named registers.
"-p 会给出第三步中删除的单词。"1p 会给出第二步中删除的行。不幸的是,由于小删除寄存器只存储一个项目,因此无法检索第一步中删除的单词。然而,如果你想要保留第一步中的文本,可以使用命名寄存器。

The Named Register

命名寄存器

The named registers are Vim’s most versatile register. It can store yanked, changed, and deleted texts into registers a-z. Unlike the previous 3 register types you’ve seen which automatically stores texts into registers, you have to explicitly tell Vim to use the named register, giving you full control.
命名寄存器是 Vim 最灵活的寄存器。它可以将拉取、更改和删除的文本存储到寄存器 a-z 中。与前面提到的会自动将文本存储到寄存器中的三种寄存器类型不同,你需要明确告诉 Vim 使用命名寄存器,这让你拥有完全的控制权。

To yank a word into register a, you can do it with "ayiw.
要将一个单词拉取到寄存器 a 中,可以执行 "ayiw

  • "a tells Vim that the next action (delete / change / yank) will be stored in register a.
    "a 告诉 Vim,下一个操作(删除/更改/拉取)将被存储在寄存器 a 中

  • yiw yanks the word.
    yiw 拉取单词

To get the text from register a, run "ap. You can use all twenty-six alphabetical characters to store twenty-six different texts with named registers.
要从寄存器 a 中获取文本,可以执行 "ap。你可以使用所有 26 个字母字符来存储 26 种不同的文本。

Sometimes you may want to add to your existing named register. In this case, you can append your text instead of starting all over. To do that, you can use the uppercase version of that register. For example, suppose you have the word "Hello " already stored in register a. If you want to add “world” into register a, you can find the text “world” and yank it using A register ("Ayiw).
有时你可能想在现有的命名寄存器中添加内容。在这种情况下,你可以追加文本,而不是重新开始。为此,你可以使用该寄存器的大写版本。例如,假设你已经在寄存器 a 中存储了单词 "Hello "。如果你想将 “world” 添加到寄存器 a 中,你可以找到文本 “world” 并使用寄存器 A("Ayiw)将其拉取。

The Read-Only Registers

只读寄存器

Vim has three read-only registers: ., :, and %. They are pretty simple to use:
Vim 有三个只读寄存器:.:%。它们的使用方法非常简单:

. Stores the last inserted text // 存储最后一次插入的文本
: Stores the last executed command-line // 存储最后执行的命令行
% Stores the name of current file // 存储当前文件的名称

If the last text you wrote was “Hello Vim”, running ".p will print out the text “Hello Vim”. If you want to get the name of current file, run "%p. If you run :s/foo/bar/g command, running ":p will print out the literal text “s/foo/bar/g”.
如果你最后一次输入的文本是 “Hello Vim”,执行 ".p 将打印出文本 “Hello Vim”。如果你想获取当前文件的名称,可以执行 "%p。如果你执行了 :s/foo/bar/g 命令,执行 ":p 将打印出字面文本 “s/foo/bar/g”。

The Alternate File Register

备用文件寄存器

In Vim, # usually represents the alternate file. An alternative file is the last file you opened. To insert the name of the alternate file, you can use "#p.
在 Vim 中,# 通常表示备用文件。备用文件是你最后打开的文件。要插入备用文件的名称,可以使用 "#p

The Expression Register

表达式寄存器

Vim has an expression register, "=, to evaluate expressions.
Vim 有一个表达式寄存器 "=,用于计算表达式。

To evaluate mathematical expressions 1 + 1, run:
要计算数学表达式 1 + 1,可以执行:

"=1+1<Enter>p

Here, you are telling Vim that you are using the expression register with "=. Your expression is (1 + 1). You need to type p to get the result. As mentioned earlier, you can also access the register from insert mode. To evaluate mathematical expression from insert mode, you can do:
在这里,你告诉 Vim 你正在使用表达式寄存器 "="。你的表达式是(1 + 1)。你需要输入 p 来获取结果。正如前面提到的,你也可以从插入模式访问寄存器。要从插入模式计算数学表达式,可以执行:

Ctrl-R =1+1

You can also get the values from any register via the expression register when appended with @. If you wish to get the text from register a:
你还可以通过表达式寄存器(在后面加上 @)获取任何寄存器中的值。如果你想获取寄存器 a 中的文本:

"=@a

Then press <Enter>, then p. Similarly, to get values from register a while in insert mode:
然后按 <Enter>,再按 p。同样,在插入模式下,要获取寄存器 a 中的值:

Ctrl-r =@a

Expression is a vast topic in Vim, so I will only cover the basics here. I will address expressions in more details in later Vimscript chapters.
表达式是 Vim 中的一个广泛主题,所以我在这里只介绍基础知识。我将在后续的 Vim 脚本章节中更详细地介绍表达式。

The Selection Registers

选择寄存器

Don’t you sometimes wish that you can copy a text from external programs and paste it locally in Vim, and vice versa? With Vim’s selection registers, you can. Vim has two selection registers: quotestar ("*) and quoteplus ("+). You can use them to access copied text from external programs.
你是否有时希望可以从外部程序复制文本并在 Vim 中本地粘贴,反之亦然?通过 Vim 的选择寄存器,你可以做到。Vim 有两个选择寄存器:quotestar"*)和 quoteplus"+)。你可以使用它们访问外部程序中复制的文本。

If you are on an external program (like Chrome browser) and you copy a block of text with Ctrl-C (or Cmd-C, depending on your OS), normally you wouldn’t be able to use p to paste the text in Vim. However, both Vim’s "+ and "* are connected to your clipboard, so you can actually paste the text with "+p or "*p. Conversely, if you yank a word from Vim with "+yiw or "*yiw, you can paste that text in the external program with Ctrl-V (or Cmd-V). Note that this only works if your Vim program comes with the +clipboard option (to check it, run :version).
如果你在外部程序(如 Chrome 浏览器)中,使用 Ctrl-C(或根据你的操作系统可能是 Cmd-C)复制了一块文本,通常你无法使用 p 在 Vim 中粘贴该文本。然而,Vim 的 "+"* 都连接到你的剪贴板,因此你可以使用 "+p"*p 粘贴文本。反之,如果你在 Vim 中使用 "+yiw"*yiw 拉取一个单词,你可以使用 Ctrl-V(或 Cmd-V)在外部程序中粘贴该文本。请注意,这只有在你的 Vim 程序带有 +clipboard 选项时才有效(要检查它,请运行 :version)。

You may wonder if "* and "+ do the same thing, why does Vim have two different registers? Some machines use X11 window system. This system has 3 types of selections: primary, secondary, and clipboard. If your machine uses X11, Vim uses X11’s primary selection with the quotestar ("*) register and X11’s clipboard selection with the quoteplus ("+) register. This is only applicable if you have +xterm_clipboard option available in your Vim build. If your Vim doesn’t have xterm_clipboard, it’s not a big deal. It just means that both quotestar and quoteplus are interchangeable (mine doesn’t either).
你可能会好奇,如果 "*"+ 做的是同样的事情,为什么 Vim 有两个不同的寄存器呢?有些机器使用 X11 窗口系统。这个系统有 3 种选择类型:主选择、次选择和剪贴板。如果你的机器使用 X11,Vim 会使用 X11 的 主选择quotestar"*)寄存器,以及 X11 的 剪贴板选择quoteplus"+)寄存器。这只有在你的 Vim 构建中包含 +xterm_clipboard 选项时才适用。如果你的 Vim 没有 xterm_clipboard,那也没关系。这仅仅意味着 quotestarquoteplus 是可以互换的(我的 Vim 也没有)。

I find doing =*p or =+p to be cumbersome. To make Vim to paste copied text from the external program with just p, you can add this in your vimrc:
我觉得执行 =*p=+p 很麻烦。为了让 Vim 只用 p 就能粘贴外部程序中复制的文本,你可以在你的 vimrc 中添加以下内容:

set clipboard=unnamed

Now when I copy a text from an external program, I can paste it with the unnamed register, p. I can also copy a text from Vim and paste it to an external program. If you have +xterm_clipboard on, you may want to use both unnamed and unnamedplus clipboard options.
现在,当我从外部程序复制文本时,我可以使用无名寄存器 p 粘贴它。我也可以从 Vim 复制文本并粘贴到外部程序中。如果你启用了 +xterm_clipboard,你可能想同时使用 unnamedunnamedplus 剪贴板选项。

The Black Hole Register

黑洞寄存器

Each time you delete or change a text, that text is stored in Vim register automatically. There will be times when you don’t want to save anything into the register. How can you do that?
每次你删除或更改文本时,该文本都会自动存储在 Vim 寄存器中。有时候,你可能不想将任何内容保存到寄存器中。那该怎么办呢?

You can use the black hole register ("_). To delete a line and not have Vim store the deleted line into any register, use "_dd.
你可以使用黑洞寄存器("_)。要删除一行且不让 Vim 将删除的行存储到任何寄存器中,可以使用 "_dd

The black hole register is like the /dev/null of registers.
黑洞寄存器就像寄存器中的 /dev/null

The Last Search Pattern Register

最后搜索模式寄存器

To paste your last search (/ or ?), you can use the last search pattern register ("/). To paste the last search term, use "/p.
要粘贴你的最后一次搜索(/?),你可以使用最后搜索模式寄存器("/)。要粘贴最后一次搜索的术语,可以使用 "/p

Viewing The Registers

查看寄存器

To view all your registers, use the :register command. To view only registers "a, "1, and "-, use :register a 1 -.
要查看所有寄存器,可以使用 :register 命令。要仅查看寄存器 “a”、“1” 和 “-”,可以使用 :register a 1 -

There is a plugin called vim-peekaboo that lets you to peek into the contents of the registers when you hit " or @ in normal mode and Ctrl-R in insert mode. I find this plugin very useful because most times, I can’t remember the content in my registers. Give it a try!
有一个名为 vim-peekaboo 的插件,它可以在你在普通模式下按下 "@,以及在插入模式下按下 Ctrl-R 时,让你查看寄存器的内容。我觉得这个插件非常有用,因为大多数时候,我记不住寄存器中的内容。你可以试试!

Executing A Register

执行寄存器

The named registers are not just for storing texts. They can also execute macros with @. I will go over macros in the next chapter.
命名寄存器不仅用于存储文本,还可以通过 @ 执行宏。我将在下一章介绍宏。

Keep in mind since macros are stored inside Vim registers, you can accidentally overwrite the stored text with macros. If you store the text “Hello Vim” in register a and you later record a macro in the same register (qa{macro-sequence}q), that macro will overwrite your “Hello Vim” text stored earlier.
请注意,由于宏存储在 Vim 寄存器中,你可能会不小心用宏覆盖存储的文本。如果你在寄存器 a 中存储了文本 “Hello Vim”,然后在同一个寄存器中录制了一个宏(qa{macro-sequence}q),那么这个宏将覆盖之前存储的 “Hello Vim” 文本。

Clearing A Register

清空寄存器

Technically, there is no need to clear any register because the next text that you store under the same register name will overwrite it. However, you can quickly clear any named register by recording an empty macro. For example, if you run qaq, Vim will record an empty macro in the register a.
从技术上讲,没有清除任何寄存器的必要,因为存储在相同寄存器名称下的下一个文本将覆盖它。然而,你可以通过录制一个空宏来快速清除任何命名寄存器。例如,如果你运行 qaq,Vim 将在寄存器 a 中记录一个空宏。

Another alternative is to run the command :call setreg('a', 'hello register a') where a is the register a and “hello register a” is the text that you want to store.
另一个选择是运行命令 :call setreg('a', 'hello register a'),其中 a 是寄存器 a,而 “hello register a” 是你想要存储的文本。

One more way to clear register is to set the content of "a register to an empty string with the expression :let @a = ''.
清除寄存器的另一种方法是使用表达式 :let @a = '' 将寄存器 “a” 的内容设置为空字符串。

Putting The Content Of A Register

粘贴寄存器的内容

You can use the :put command to paste the content of any one register. For example, if you run :put a, Vim will print the content of register a below the current line. This behaves much like "ap, with the difference that the normal mode command p prints the register content after the cursor and the command :put prints the register content at newline.
你可以使用 :put 命令粘贴任何一个寄存器的内容。例如,如果你运行 :put a,Vim 将在当前行下方打印寄存器 a 的内容。这与 "ap 的行为非常相似,不同之处在于普通模式命令 p 在光标后打印寄存器内容,而命令 :put 在新行打印寄存器内容。

Since :put is a command-line command, you can pass it an address. :10put a will paste text from register a to below line 10.
由于 :put 是一个命令行命令,你可以给它传递一个地址。:10put a 将把寄存器 a 中的文本粘贴到第 10 行下方。

One cool trick to pass :put with the black hole register ("_). Since the black hole register does not store any text, :put _ will insert a blank line instead. You can combine this with the global command to insert multiple blank lines. For example, to insert blank lines below all lines that contain the text “end”, run :g/end/put _. You will learn about the global command later.
一个很酷的技巧是将 :put 与黑洞寄存器("_)一起使用。由于黑洞寄存器不存储任何文本,:put _ 将插入一个空行。你可以将它与全局命令结合起来插入多个空行。例如,要将空行插入到包含文本 “end” 的所有行下方,可以运行 :g/end/put _。你稍后会学到全局命令。

Learning Registers The Smart Way

聪明地学习寄存器

You made it to the end. Congratulations! If you are feeling overwhelmed by the sheer information, you are not alone. When I first started learning about Vim registers, there were way too much information to take at once.
你已经到了最后。恭喜!如果你觉得信息量太大,你并不孤单。当我第一次开始学习 Vim 寄存器时,信息量实在太大,无法一次吸收。

I don’t think you should memorize all the registers immediately. To become productive, you can start by using only these 3 registers:
我认为你不需要立即记住所有的寄存器。为了提高工作效率,你可以先从使用以下 3 个寄存器开始:

  1. The unnamed register ("").
    无名寄存器 ("")

  2. The named registers ("a-z).
    命名寄存器 ("a-z)

  3. The numbered registers ("0-9).
    编号寄存器 ("0-9)

Since the unnamed register defaults to p and P, you only have to learn two registers: the named registers and the numbered registers. Gradually learn more registers when you need them. Take your time.
由于无名寄存器默认对应 pP,你只需要学习两个寄存器:命名寄存器和编号寄存器。当你需要时,逐渐学习更多的寄存器。不要着急。

The average human has a limited short-term memory capacity, about 5 - 7 items at once. That is why in my everyday editing, I only use about 5 - 7 named registers. There is no way I can remember all twenty-six in my head. I normally start with register a, then b, ascending the alphabetical order. Try it and experiment around to see what technique works best for you.
普通人短期记忆的容量有限,大约一次能记住 5 - 7 个项目。这就是为什么在我的日常编辑中,我只使用大约 5 - 7 个命名寄存器。我没办法把全部 26 个都记在脑子里。我通常从寄存器 a 开始,然后是 b,按字母顺序依次往上。你可以试试看,多试验一下,看看哪种方法最适合你。

Vim registers are powerful. Used strategically, it can save you from typing countless repeating texts.
Vim 寄存器非常强大。如果使用得当,它可以帮你避免输入无数重复的文本。


Advanced Vim registers

Posted on 2012-10-24

Registers in Vim are best thought of as scratch spaces for text, some of which are automatically filled by the editor in response to certain actions. Learning how to use registers fluently has a lot of subtle benefits, although it takes some getting used to because the syntax for using them is a little awkward.
Vim 中的寄存器最好被看作是文本的暂存空间,其中一些会根据某些操作由编辑器自动填充。学会熟练使用寄存器会带来很多微妙的好处,尽管一开始可能会觉得有些不习惯,因为使用它们的语法有点笨拙。

If you’re reasonably fluent with Vim by now, it’s likely you’re already familiar with the basic usage of the 26 named registers, corresponding to the letters of the alphabet. These are commonly used for recording macros; for example, to record a series of keystrokes into register a, you might start recording with qa, and finish with q; your keystrokes could then be executed with @a.
如果你对 Vim 已经相当熟悉,那么你可能已经了解了 26 个 命名寄存器 的基本用法,它们分别对应字母表中的字母。这些寄存器通常用于录制宏;例如,要将一系列按键记录到寄存器 a 中,你可以用 qa 开始录制,用 q 结束录制;然后可以用 @a 执行这些按键。

Similarly, we can store text from the buffer itself rather than commands in these registers, by prepending "a to any command which uses a register, such as the c, d, and y commands:
同样地,我们可以通过在使用寄存器的命令(如 cdy 命令)前加上 "a,将缓冲区中的文本而不是命令存储到这些寄存器中:

  • "ayy — Read current line into register a.

    "ayy — 将当前行读入寄存器 a

  • "bP — Paste contents of register b above current line.

    "bP — 将寄存器 b 的内容粘贴到当前行上方

  • "cc3w — Change three words, putting the previous three words into register c.

    "cc3w — 更改三个单词,将之前的三个单词放入寄存器 c

Like many things in Vim, there’s a great deal more functionality to registers for those willing to explore.
就像 Vim 中的许多其他功能一样,寄存器还有许多值得探索的功能。

Note that here I’ll be specifically ignoring the *, +, and ~ registers; that’s another post about the generally unpleasant business of making Vim play nice with system clipboards. Instead, I’ll be focussing on stuff that only applies within a Vim session. All of this is documented in :help registers.
请注意,这里我将特别忽略 *+~ 寄存器;那是一个关于如何让 Vim 与系统剪贴板友好相处的不愉快话题,会在另一篇文章中讨论。相反,我将专注于只在 Vim 会话中适用的内容。所有这些内容都在 :help registers 中有详细说明。

Capital registers

大写寄存器

Yanking and deleting text into registers normally replaces the previous contents of that register. In some cases it would be preferable to append to a register, for example while cherry-picking different lines from the file to be pasted elsewhere. This can be done by simply capitalizing the name of the register as it’s referenced:
通常情况下,将文本拉取或删除到寄存器中会 替换 该寄存器的先前内容。在某些情况下,将文本 追加 到寄存器会更有用,例如从文件中挑选不同的行以粘贴到其他地方。只需将寄存器名称大写即可实现这一点:

  • "ayyReplace the contents of register a with the current line.

    "ayy — 用当前行 替换 寄存器 a 的内容

  • "AyyAppend the current line to register a.

    "Ayy — 将当前行 追加 到寄存器 a

This works for any context in which an alphabetical register can be used. Similarly, to append to a macro already recorded in register a, we can start recording with qA to add more keystrokes to it.
这适用于任何可以使用字母寄存器的上下文。同样地,要向已经记录在寄存器 a 中的宏追加内容,可以用 qA 开始录制,以添加更多的按键。

Viewing register contents

查看寄存器内容

A good way to start getting a feel for how all the other registers work is to view a list of them with their contents during an editing session with :registers. This will show the contents of any register used in the editing session. It might look something like this, a little inscrutable at first:
查看寄存器内容的一个好方法是在编辑会话中使用 :registers 查看它们的列表及其内容。这将显示在编辑会话中使用过的任何寄存器的内容。一开始可能会看起来有点难以理解,就像这样:

:registers
--- Registers ---
"" Note that much of it includes  // 注意,其中大部分包括
"0 execut
"1 ^J^J
"2 16 Oct (2 days ago)^J^Jto Jeff, Alan ^JHi Jeff (cc Alan);^J^JPlease 
"3 <?php^Jheader("Content-Type: text/plain; charset=utf-8");^J?>^J.^J
"4 ^J
"5 Business-+InternationalTrade-TelegraphicTransfers-ReceivingInternati
"6 ../^J
"7  diff = auto^J status = auto^J branch = auto^J interacti
"8 ^J[color]^J ui = auto^J diff = auto^J status = auto^J br
"9  ui = true^J
"a escrow
"b 03wdei^R=2012-^R"^M^[0j
"c a
"e dui{<80>kb^[^[
"g ^[gqqJgqqjkV>JgqqJV>^[Gkkkjohttp://tldp.org/LDP/abs/html/ ^[I[4]: ^[k
"h ^[^Wh:w^Mgg:w^M^L:w^Mjk/src^Mllhh
"j jjjkkkA Goo<80>kb<80>kb<80>kbThis one is good pio<80>kbped through a
"- Note that much of it includes   // 注意,其中大部分包括
". OIt<80>kb<80>kb<80>kbIt might looks <80>kb<80>kb something like thi
": register
"% advanced-vim-registers.markdown
"/ Frij

The first column contains the name of the register, and the second its contents. The contents of any of these registers can be pasted into the buffer with "ap, where a is the name of any of them. Note that there are considerably more registers than just the named alphabetical ones mentioned above.
第一列是寄存器的名称,第二列是其内容。这些寄存器中的任何内容都可以用 "ap 粘贴到缓冲区中,其中 a 是它们中的任何一个的名称。请注意,寄存器的数量远远不止上面提到的字母命名的那些。

Unnamed register

无名寄存器

The unnamed register is special in that it’s always written to in operations, no matter whether you specified another register or not. Thus if you delete a line with dd, the line’s contents are put into the unnamed register; if you delete it with "add, the line’s contents are put into both the unnamed register and into register a.
无名寄存器 的特殊之处在于,无论你是否指定了另一个寄存器,它都会在操作中被写入。因此,如果你用 dd 删除一行,该行的内容将被放入无名寄存器;如果你用 "add 删除它,该行的内容将被放入无名寄存器 寄存器 a

If you need to explicitly reference the contents of this register, you can use ", meaning you’d reference it by tapping " twice: "". One handy application for this is that you can yank text into the unnamed register and execute it directly as a macro with @".
如果你需要明确引用这个寄存器的内容,你可以使用 ",也就是说,你可以通过连续按两次 " 来引用它:""。一个方便的应用是,你可以将文本拉取到无名寄存器中,并直接用 @" 将其作为宏执行。

Man, and you thought Perl looked like line noise.
伙计,你以为 Perl 看起来像行噪声呢。(调侃 Perl 语言的语法复杂性,让人觉得它看起来像是一堆杂乱无章的字符。)

Black hole register

黑洞寄存器

Another simple register worth mentioning is the black hole register, referenced with "_. This register is special in that everything written to it is discarded. It’s the /dev/null of the Vim world; you can put your all into it, and it’ll never give anything back. A pretty toxic relationship.
另一个值得一提的简单寄存器是 黑洞寄存器,用 "_ 引用。这个寄存器的特殊之处在于,写入它的所有内容都会被丢弃。它是 Vim 世界中的 /dev/null;你可以把一切都放进去,但它永远不会给你任何回报。一种相当有毒的关系。

This may not seem immediately useful, but it does come in handy when running an operation that you don’t want to clobber the existing contents of the unnamed register. For example, if you deleted three lines into the unnamed register with 3dd with the intent of pasting them elsewhere with p, but you wanted to delete another line before doing so, you could do that with "_dd; line gone, and no harm done.
这可能看起来不那么有用,但在执行一个操作时,如果你不想覆盖无名寄存器的现有内容,它就派上用场了。例如,如果你用 3dd 将三行内容删除到无名寄存器中,打算用 p 将它们粘贴到其他地方,但在那之前你想再删除一行,你可以用 "_dd 来做到这一点;行被删除了,而且不会造成任何伤害。

Numbered registers

编号寄存器

The read-only registers 0 through 9 are your “historical record” registers. The register 0 will always contain the most recently yanked text, but never deleted text; this is handy for performing a yank operation, at least one delete operation, and then pasting the text originally yanked with "0p.
只读寄存器 09 是你的 “历史记录” 寄存器。寄存器 0 将始终包含最近 拉取的文本,但永远不会包含删除的文本;这对于执行一个拉取操作、至少一个删除操作,然后用 "0p 粘贴最初拉取的文本非常有用。

The registers 1 through 9 are for deleted text, with "1 referencing the most recently deleted text, "2 the text deleted before that, and so on up to "9.
寄存器 19 用于 删除的文本,其中 "1 指向最近删除的文本,"2 指向之前删除的文本,依此类推,直到 "9

The small delete register

小删除寄存器

This read-only register, referenced by "-, stores any text that you deleted or changed that was less than one line in length, unless you specifically did so into some other named register. So if you just deleted three characters with 3x, you’ll find it in here.
这个只读寄存器,用 "- 引用,存储了你删除或更改的所有小于一行长度的文本,除非你特别将其存储到其他命名寄存器中。所以如果你刚刚用 3x 删除了三个字符,你会在这里找到它。

Last inserted text register

最后插入的文本寄存器

The read-only register ". contains the text that you last inserted. Don’t make the mistake of using this to repeat an insert operation, though; just tap . for that after you leave insert mode, or have the foresight to prepend a number to your insert operation; for example, 6i.
只读寄存器 ". 包含你最后一次插入的文本。不过,不要用它来重复插入操作;离开插入模式后,只需按 . 就可以做到这一点,或者在插入操作前加上一个数字,例如 6i

Filename registers

文件名寄存器

The read-only register "% contains the name of the current buffer’s file. Similarly, the "# register contains the name of the alternate buffer’s file.
只读寄存器 "% 包含当前缓冲区文件的名称。同样,"# 寄存器包含备用缓冲区文件的名称。

Command registers

命令寄存器

The read-only register ": contains the most recently executed : command, such as :w or :help. This is likely only of interest to you if you’re wanting to paste your most recent command into your Vim buffer. For everything else, such as repeating or editing previous commands, you will almost certainly want to use the command window_.
只读寄存器 ": 包含最近执行的 : 命令,例如 :w:help。这可能只在你想要将最近的命令粘贴到 Vim 缓冲区时对你感兴趣。对于其他所有事情,比如重复或编辑之前的命令,你几乎肯定想使用命令窗口。

Search registers

搜索寄存器

The read-only register / contains the most recent search pattern; this can be handy for inserting the search pattern on the command line, by pressing Ctrl-R and then / — very useful for performing substitutions using the last search pattern.
只读寄存器 / 包含最近的搜索模式;这可以通过按下 Ctrl-R 然后 / 将搜索模式插入到命令行中,非常有用,特别是当你想使用最后一个搜索模式进行替换操作时。

Expression register

表达式寄存器

Here’s the black sheep of the bunch. The expression register = is used to treat the results of arbitrary expressions in register context. What that means in actual real words is that you can use it as a calculator, and the result is returned from the register.
这是这一群中的异类。表达式寄存器 = 用于在寄存器上下文中处理任意表达式的结果。用实际的话来说,你可以用它来当计算器,结果会从寄存器返回。

Whenever the expression register is referenced, the cursor is put on the command line to input an expression, such as 2+2, which is ended with a carriage return.
每次引用表达式寄存器时,光标都会被置于命令行上输入一个表达式,例如 2+2,然后以回车结束。

This means in normal mode you can type "=2+2<Enter>p, and 4 will be placed after the cursor; in insert or command mode you can use Ctrl-R then =2+2<Enter> for the same result. If you don’t find this syntax as impossibly awkward as I do, then this may well suit you for quick inline calculations … personally, I’d drop to a shell and bust out bc for this.
这意味着在普通模式下,你可以输入 "=2+2<Enter>p,然后 4 会被放在光标后面;在插入模式或命令模式下,你可以使用 Ctrl-R 然后输入 =2+2<Enter>,得到相同的结果。如果你不像我一样觉得这种语法不可能地笨拙,那么这可能很适合你进行快速的行内计算……我个人会切换到 shell 中,然后使用 bc 来完成这个操作。

Knowing your registers well isn’t as profound a productivity boost as squelching a few of the other Vim anti-patterns_, but it can certainly save you some of the annoyance of lost text.
熟悉寄存器并不像消除其他一些 Vim 反模式那样极大地提高生产力,但它确实可以节省一些因丢失文本而带来的烦恼。

This entry was posted in Vim, expression by Tom Ryder.


Registers: the Good, the Bad, and the Ugly Parts

寄存器:好的、坏的和丑陋的部分

Nov 25, 2013

To the newcomer, Vim’s way of doing things may seem strange, but with familiarity it becomes natural. Many of Vim’s features seemed odd to me at first, but when I got used to them I recognised that they had their own particular elegance. However, there’s one feature of Vim that still feels awkward to me: using registers for copy and paste.
对于新人来说,Vim 的做事方式可能看起来很奇怪,但熟悉后就会变得自然而然。起初,Vim 的许多特征对我来说似乎很奇怪,但当我习惯了它们时,我发现它们有自己独特的优雅。但是,Vim 的一个功能仍然让我感到尴尬:使用寄存器进行复制和粘贴。

The Good Parts

好的部分

There’s plenty to like about Vim’s registers. I’ve produced a series of 7 screencasts_ that go into depth about how registers can be used for copy and paste. As far as I’m concerned, that’s all good stuff. But registers aren’t only useful for copy and paste. We can also create and execute macros, by recording our keystrokes into a register then playing back those keystrokes later.
Vim 的寄存器有很多值得喜欢的地方。我制作了一系列 7 个截屏视频,深入探讨了如何使用寄存器进行复制和粘贴。就我而言,这都是好东西。但是寄存器不仅可用于复制和粘贴。我们还可以创建和执行宏,方法是将我们的击键记录到寄存器中,然后播放这些击键。

The fact that registers are multi-purpose means that after recording a macro we can easily make changes to it. For example, we could record our keystrokes into a register, then paste that register into the document, edit the keystrokes in place, then yank the modified version back into a register. (See Practical Vim_, tip 71: Edit the contents of a macro for a demonstration.) I like that flexibility.
寄存器是多用途的,这意味着在录制宏后,我们可以轻松地对其进行更改。例如,我们可以将击键记录到寄存器中,然后将该寄存器粘贴到文档中,就地编辑击键,然后将修改后的版本拉回寄存器中。

I also like how Vim exposes useful information through the search_ and read-only registers_: @/ contains the current search pattern, @: contains the last Ex command, @. contains the last inserted text, and @% contains the filename of the current buffer.
我也喜欢 Vim 通过搜索和只读寄存器公开有用信息的方式:@/ 包含当前搜索模式,@: 包含最后一个 Ex 命令,@. 包含最后插入的文本,@% 包含当前缓冲区的文件名。

The Bad Parts

坏的部分

The registers numbered "1 through "9 are a source of frustration for me. If you skim-read the documentation for Vim’s numbered registers_, they sound promising:
编号为 "1"9 的寄存器对我来说是一个令人沮丧的根源。如果你略读一下 Vim 的编号寄存器的文档,它们听起来很有希望:

Vim shifts the previous contents of register 1 into register 2, 2 into 3, and so forth, losing the previous contents of register 9.
Vim 将寄存器 1 的先前内容移到寄存器 2 中,将 2 移到寄存器 3 中,以此类推,丢失寄存器 9 的先前内容。

It seems as though the registers numbered "1 - "9 provide something like a clipboard history, which sounds handy. This would be further enhanced by a little-known feature of the . command: when used to repeat "1p, the dot command increments the register number (see :help redo-register_):
编号为 "1 - "9 的寄存器似乎提供了类似于剪贴板历史记录的内容,这听起来很方便。. 命令的一个鲜为人知的功能将进一步增强这一点:当用于重复 "1p 时,点命令会增加寄存器号):

you can use a special feature of the repeat command .. It will increase the number of the register used. So if you first do "1P, the following . will result in a "2P. Repeating this will result in all numbered registers being inserted.
你可以使用 repeat 命令 . 的特殊功能。它将增加使用的寄存器的数量。因此,如果你先执行 "1P,接下来的 . 将导致 "2P。重复此操作将导致插入所有编号的寄存器。

Not only does Vim maintain a sort of clipboard history, but it also provides a convenient method for iterating through the clipboard history. That sounds like a good thing, so why have I filed this under ‘The Bad Parts’?
Vim 不仅维护了一种剪贴板历史记录,而且还提供了一种遍历剪贴板历史记录的便捷方法。这听起来是一件好事,那么为什么我要把它归类到 “坏的部分” 下呢?

There’s a catch: Vim never writes yank operations to register "1. Instead, yanked text is written to register "0, which is isolated from the mechanism that propagates values through "1 to "9. That means that the clipboard history is incomplete. Registers "1 - "9 only record deletions, not yanks.
这里有一个问题:Vim 从不向寄存器 "1 写入拉取操作。相反,被拉取的文本被写入寄存器 "0,它与通过 "1 将值传播到 "9 的机制隔离。这意味着剪贴板历史记录是不完整的。寄存器 "1 - "9 仅记录删除,不记录拉取。

And when I say that registers "1 - "9 only record deletions, I have to add a further caveat: if the range of text being deleted spans less than one line, it will be written to "-, the small delete register. That is, unless you prefix the delete operation with a named register. In that case, the text will be written to the named register and to register "1, but not to "-.
当我说寄存器 "1 - "9 仅记录删除时,我必须进一步补充一个警告:如果要删除的文本范围小于一行,它将被写入 "-,即 小删除寄存器。也就是说,除非在删除操作前面加上命名寄存器。在这种情况下,文本将被写入命名寄存器和寄存器 "1,但不会写入 "-

I’ve compiled a table showing which registers are populated by various combinations of yank/delete operations, over a characterwise/linewise range, with or without a named register (see this gist_ for details of how I compiled this information):
我编制了一个表格,显示了在字符/行范围内,有或没有命名寄存器,哪些寄存器由各种拉取/删除操作组合填充:

operation "" (default) "0 (yank) "1 (numbered) "a (named) "- (small delete)
yw X X - - -
yy X X - - -
"ayw X - - X -
"ayy X - - X -
dw X - - - X
dd X - X - -
"adw X - X X -
"add X - X X -

There are so many idiosyncrasies in this table that it’s hard to decide what’s a rule and what’s an exception! It’s needlessly complicated. If you’re considering committing this chart to memory, I would urge you not to bother.
这个表格中有太多的特质,很难决定什么是规则,什么是例外!这没有必要地复杂。如果你正在考虑将这张图表牢记在心,我强烈建议你不要打扰。

The Ugly Parts

丑陋的部分

Vim uses non-standard terminology to describe cut, copy, and paste operations. As I’ve noted before_: ‘put’ and ‘paste’ are easily interchangeable, and the word ‘yank’ becomes synonymous with ‘copy’ when you get used to it, but Vim’s use of the word ‘delete’ is problematic.
Vim 使用非标准术语来描述剪切、复制和粘贴操作。正如我之前提到的:‘put’ 和 ‘paste’ 很容易互换,当你习惯了 ‘yank’ 这个词时,它就变成了 ‘copy’ 的同义词,但 Vim 对 ‘delete’ 这个词的使用是有问题的。

In most text editing contexts the word delete means remove. But Vim’s delete operation copies the text into a register, then removes it from the document. In other words, Vim’s delete operation behaves like the standard cut command. I find Vim’s terminology to be unhelpful, so I try to make a point of describing the d{motion} command as “cut the specified text” (rather than “delete the specified text”). Likewise for x, c, s, and so on.
在大多数文本编辑上下文中,单词 delete 的意思是 remove。但是 Vim 的 delete 操作将文本复制到寄存器中,然后将其从文档中删除。换句话说,Vim 的 delete 操作就像标准的 cut 命令。我发现 Vim 的术语没有帮助,所以我试图将 d{motion} 命令描述为 “cut the specified text”(而不是 “delete the specified text”)。xcs 等也是如此。

The fact that x, s, d, and c all cut by default makes it awkward to perform a true deletion. To really delete text (without writing to a register), we have to prefix each of these commands with "_, the blackhole register. That’s bizarre! More often than not, when I use Vim’s delete operation, I only want to remove the text from the document. I don’t want to write it to a register and I consider that to be an unfortunate side-effect.
xsdc 都默认被剪切,这使得执行真正的删除变得很尴尬。要真正删除文本(不写入寄存器),我们必须为每个命令加上 "_,即黑洞寄存器。太奇怪了!通常,当我使用 Vim 的删除操作时,我只想从文档中删除文本。我不想把它写到寄存器上,我认为这是一个不幸的副作用。

On the other hand, I definitely want to write the text to a register when I use the yank command (after all, that’s the only thing it does!). It’s frustrating that the yank command writes to "0, overwriting my previous yank. Whereas the delete command writes text that I may not even want to keep to "1, preserving the previous eight deletions in registers "2 - "9.
另一方面,当我使用 yank 命令时,我肯定想将文本写入寄存器(毕竟,这是它唯一能做的事情!)。令人沮丧的是,yank 命令写入 "0,覆盖了我之前的 yank。而 delete 命令写入我甚至可能不想保留到 "1 的文本,将前八次删除保留在寄存器 "2 - "9 中。

So what?

那又怎样?

Cut is not a sensible default behaviour for a command named ‘delete’. The terminology is misleading, but the behaviour itself is also unfortunate. Vimcasts episode #52, Meet the yank register_, shows an example workflow where this behaviour acts as an impediment. It would be better if Vim provided two distinct commands: the delete operation would only remove text from the document, while the cut operation would remove text from the document and write it to a register. That Vim’s x, s, d, and c “delete operations” write text to a register is ugly.
对于名为 ‘delete’ 的命令来说,Cut 不是一个明智的默认行为。术语具有误导性,但行为本身也是不幸的。Vimcasts 第 #52 集 Meet the yank register 展示了一个示例工作流,其中此行为充当障碍。如果 Vim 提供两个不同的命令会更好:delete 操作只会从文档中删除文本,而 cut 操作将从文档中删除文本并将其写入寄存器。Vim 的 xsdc 的 “delete operations” 将文本写入寄存器是丑陋的。

I can’t find any redeeming features in the behaviour of Vim’s numbered registers, which makes me think they’re just plain bad. They get almost half-way to behaving as a proper clipboard history, but that’s not good enough. A half-cooked feature is a feature wasted.
我在 Vim 的编号寄存器的行为中找不到任何可赎回的功能,这让我觉得它们简直太糟糕了。它们几乎已经完成了一半的行为,就像一个正确的剪贴板历史记录一样,但这还不够好。半生不熟的功能是浪费的功能。

I’ve learned to live with the good parts of Vim’s copy/paste feature set. The good parts are good enough to get by with, but they’re not as good as they could be. That frustrates me.
我已经学会了接受 Vim 的复制/粘贴功能集的优点。好的部分已经足够好了,但它们并没有达到应有的水平。这让我很沮丧。

I have written my thoughts on how to fix Vim’s registers in the form of a README for cutlass.vim - a plugin that doesn’t yet exist. I’d also like to give a shout out to Steve Vermeulen, who has already implemented some of the same features (and many more features besides) in his vim-easyclip plugin, which you can install and use today.
我已经以 cutlass.vim 的 README 的形式写下了我关于如何修复 Vim 寄存器的想法 - 一个尚不存在的插件。我还想感谢 Steve Vermeulen,他已经在他的 vim-easyclip 插件中实现了一些与我绘制的相同的功能(以及更多功能),你现在就可以安装并使用。


vim 中寄存器使用和 vim 标记

rainysia 于 2012-07-06 13:24:36 发布

一、官方帮助手册

: help registers
: help :registers

二、寄存器分类

  1. 无名(unnamed)寄存器 " ",缓存最后一次操作内容。
  2. 数字(numbered)寄存器 "0 "9,缓存最近操作内容,复制与删除有别。 "0寄存器缓存最近一次复制的内容, "1 - "9缓存最近9次删除内容。
  3. 行内删除(small delete)寄存器 " -,缓存行内删除内容。
  4. 具名(named)寄存器 "a "z "A - "Z,指定时可用。
  5. 只读(read - only)寄存器 " : " . " % " #,分别缓存最近命令、最近插入文本、当前文件名、当前交替文件名。
  6. 表达式(expression)寄存器 " =,只读,用于执行表达式命令。
  7. 选择及拖拽(selection and drop)寄存器 " * " + " ~,存取GUI选择文本,可用于与外部应用交互,使用前提为系统剪切板(clipboard)可用。
  8. 黑洞(black hole)寄存器 " _,不缓存操作内容(干净删除)。
  9. 模式寄存器(last search pattern) " /,缓存最近的搜索模式。

三、查看寄存器内容

  • : reg :查看所有寄存器内容。
  • : reg 寄存器名 :查看单个寄存器内容 。比如 : reg _: reg *: reg 1: reg 9: reg a等等。

数字寄存器,也是最常用的 从0 - 9 。如果不指定寄存器的名字,那么删除的内容,vim 默认是存到 1 ,复制内容是存到 0 号寄存器。如果继续删除,那么原来 1 的内容就转到 2 ,类推,当删除超过 9 的时候,原先的 8 号数字寄存器就转到 9 ,原先 9 的数字寄存器内容就会丢失。

实验1

先在vim里面输入1 - 0 10个数字,每个数字一行,接着从0 9 8 7 6 5 4 3 2依次 dd删除,然后: reg查看寄存器,接着 yy复制数字1的这行,可以看见 "0寄存器的值是1 , "1 "9寄存器依次是2~0。

使用 p来粘贴,如果最近一次操作是复制,那么 p就会添加 "0寄存器的内容,如果最近一次操作是删除那么就添加 "1寄存器的内容 ,如果要粘贴其它数字寄存器的内容,使用 "? p来粘贴,比如要粘贴 "2寄存器里面的,则在vim命令模式下输入 "2 p就可以取出 "2寄存器里面的内容了。其他的寄存器都是通过 "? p来访问使用的。

具名寄存器(字母寄存器)

也就是名称是单个英文字母, "a "b "c,....,"z ,使用时,在复制或者删除命令 y或者 d时,在前面加上字母寄存器的字母名称就可以了,或者是直接在删除或者复制命令后加上字母寄存器的字母。比如: y n就是复制当前行到 "n字母寄存器 ,: 5,10 y m复制5到10行内容到 "m字母寄存器 。

: pu! n :将字母寄存器 "n的内容粘贴到当前行之前 ,也可以使用 "mP效果一样。
: p n :粘贴字母寄存器 "n的内容到当前行的下一行 ,也可以使用 "n p效果一样。

(命令模式下 : y: d: pu分别是复制、删除和粘贴 。一般模式下 "寄存器名 y “寄存器名 d "寄存器名 p代表着复制、删除和粘贴 )

实验 2

  • "a yy :就是复制当前行到 "a字母寄存器中。
  • "b 3yy :复制当前行和下面2行到 "b字母寄存器。
  • "a p :粘贴 "a字母寄存器的内容。
  • "c d2l :向右删除2个字符并且把内容存到字母寄存器 "c中 。
  • "c p :粘贴 "c字母寄存器里面的内容。
  • "d 3dd :删除当前行和下面2行并且把内容存到字母寄存器 "d中 。
  • "f df. :删除当前位置到句号并且把内容存到字母寄存器 "f中。
  • "g d'c :删除当前位置到标记c位置并且把内容存到字母寄存器 "g中。

同一个字母的大写和小写表示的是同一个寄存器,但是行为会不同,字母寄存器的名称大写时,当使用大写的寄存器进行复制或者删除文本时,原先的字母寄存器中的内容会被保留,刚删除或复制的内容则附加到原来字母寄存器内容的后面。字母寄存器只有在指定时才被使用。

无名寄存器

" "保存最近一次复制或删除的文本。就是 p命令默认使用的寄存器。

短删除寄存器

" -(The small delete register)。事实上刚删除的文本并不一定被送到数字寄存器,如果删除的文本不含换行符(不足一整句)则文本被送至这个寄存器。如 x d2h这两条命令删除的文本都会被送到这个寄存器。注意下在这条命令虽然删除了一整行的文本但因不含换行符所以也被送到这个寄存器 0d$

只读寄存器

" : " . " % " #,它们分别用来保存最近一次在命令行窗口使用的命令、最近一次插入的文本、当前编辑的文件名、当前的替代文件名。

表达式寄存器

" =

选择与拖放的寄存器

" * " + " ~,在Windows中这几个寄存器就是剪贴板。在Linux中它们也是剪贴板——但这几个寄存器是有所区别的。

黑洞寄存器

" _,删除操作会影响现有数字寄存器的内容。前一个数字寄存器的值传给后一个数字寄存器, "9的内容被丢弃,新删除的文本则放入 "1。这至少有两个直接的影响,一是 "9的内容被丢弃;二是寄存器中文本的位置都发生了变化。而复制操作会改变 "0的值。如果你不希望删除或复制的操作影响数字寄存器的话就使用这个寄存器。使用这个寄存器进行删除或复制的内容都会被丢弃——这还可以提高一点速度节省一点空间。

搜索式样寄存器

" /,保存上一次搜索所使用的式样。注意这也包括了 s命令中所使用的搜索式样。

寄存器有26个字母寄存器可以使用 ;可以使用大写字母将文本附加到已有内容后。如果在你关闭文件之前还没想到这将这些内容贴在哪里也没关系, 用: wviminfo my_viminfo命令。下一次编辑时输入: rviminfo! my_viminfo或者在命令行用这个命令运行 gvim - i my_viminfo myfile: reg看寄存器的内容都在的。

四、寄存器是个变量——特殊的变量

只要在前面加上一个@号就可以用变量的方式访问寄存器。所以,变量的操作也同样适用于寄存器。

  • 给寄存器赋值
    let @e = "开始\\<CR>"
    let @E = "结束"
    echo @e
    开始
    结束
    
  • 将寄存器作为表达式的一部分
    let my_var = @a. @c
    
  • 清空寄存器
    " 注意:不能用unlet清除寄存器。
    : let @e = " "
    

在编辑窗口与命令窗口间交换内容

编辑窗口的文本可以放进寄存器。搜索式样和上一条Ex命令被放进了只读寄存器 " / " :

已知寄存器的内容可以在贴到编辑窗口。可以在命令窗口作为变量使用。那有没有办法在命令窗口插入寄存器的内容呢 ?有没有办法在搜索式样中插入寄存器的内容呢 ?

比如,假设在寄存器e中保存着一个文件名 :“这是一个保存在寄存器中的很长的文件名.txt”。而我想使用: w命令保存一个当前编辑文件的副本——使用寄存器e中的那个文件名。如果使用: w @e的话,文件名将是“@e”而不是“这是一个保存在寄存器中的很长的文件名.txt”。这时该怎么办呢 ?考虑到寄存器也是变量,我们可以使用寄存器的传统办法。

  1. 方法一 :使用: execute命令
    写入以 "e为名的寄存器中 :
: exe "w ". @e
  1. 方法二 :使用Ctrl - R转义
    搜索寄存器e的内容。<Ctrl - R>表示用户在这里按了组合键Ctrl - R——不要直接输入<Ctrl - R>这8个字符。
/ <Ctrl - R>e /

使用<Ctrl - R>的方式可适用于各种输入的环境中 :在插入模式输入时、在命令窗口输入时、在搜索时。在插入模式时要输入寄存器内容并不需要退回到一般模式再使用 p指令,可以直接按<Ctrl - R>e,当然e可以改成相应的寄存器名。在命令窗口与搜索时也是一样 :按Ctrl - R输入寄存器名。

提示 :除了一些不接受变量作为参数,不能使用寄存器名称的情况外,还有一些情况也要求插入寄存器的内容。有时我们插入寄存器的内容而不使用寄存器变量是因为我们可能还需要手工对寄存器的内容进行一些编辑。

无名寄存器总是保存着最近一次复制或删除的内容。不带寄存器名地使用 p就可以添加该寄存器的内容到当前位置了。但是既然“无名”该怎么在命令窗口使用这个存器呢 ?又怎么插入无名寄存器的内容呢 ?答案是使用 @ ",插入也是一样按Ctrl - R再按输入 "就可以了。

现在总结一下 : " :保存了上一条Ex命令。 " /保存了上一条搜索式样。字母寄存器及数字寄存器中可以保存编辑的文本。并且我们也可以在不同的环境中插入寄存器的内容。通过寄存器我们可以方便地在命令窗口编辑窗口以及搜索中交换内容。相对而言一般的变量就没这么方便,你只能在命令行中使用变量也只能是命令行中给变量赋值。

在buffer之间及程序之间交换内容

寄存器是全局的变量。在Vim中打开的所有文件,共享这些寄存器。你可以在不同的文件之间交换内容。

通过寄存器 " * " +,Vim可以与其他程序交换信息。在Windows中这两个寄存器是一样的。在Linux中这两个寄存器则有所不同。
: help gui - selections
: help x11 - selection

寄存器可以做为宏

跟一般的变量相比寄存器还有一个最大的特点就是寄存器本身可以做为宏使用。如果你有用过一般模式命令 q的话就会发现 q录制的击键序列就是存在寄存器中的,并且可以直接使用寄存器执行命令。现在做做实验,新建一文档随便输入几行文字。输入 :

qeggddq

上面这条命令录制了一个宏并保存到寄存器e中。这个宏的作用是回到第一行并删除该行。现在看一下寄存器的内容 :

: reg e

就是你刚才的键盘命令 ggdd。要运行刚录制的键盘操作在一般模式输入 @e就可以运行了,输入 3@e会将前三行删除。

当然你不一定要用 q来录制宏——因为寄存器也是变量。

: let @e = "/删除本行/^Mdd : w^M"
@e

上面的 ^M表示的是回车键。可不是输入 ^再输入 M,而是输入Ctrl - V(Windows是Ctrl - Q)再按回车键这时就会出现 ^M表示这是一个回车键。常见的还有 ^\[表示的是<ESC>键。输入的方法也是一样按Ctrl - V再按Esc键。这样输入控制字符的方式是传统的Vi方法。在Vim中也支持用按键名表示这些控制字符。比如<CR>表示回车键,所以上面的命令也可表示为 :

: let @e = "/删除本行/\\<CR>dd : w\\<CR>"

这里一定要用双引号,我们在“脚本”一篇中已经讲到了,在单引号中的字串会被当成普通字串。后面这种表示控制字符的方式与 'cpoptions'的设置有关,虽然在默认情况下都是可行的但是建议使用第一种方式。不过为了更好的可读性在教程中我们还是可能使用后面这种方式表示控制字符。

正因为寄存器可以直接执行所以 " :可以用来执行上一条在命令窗口使用的命令 :

:@:

记得最后要按回车执行。当然现在由于命令行的历史功能这种用法没有什么实用价值。

在重定向命令中使用

重定向命令(: redir)是一个较常用的技巧。所有的字母寄存器、 @ *、无名寄存器( @ ")都可以在重定向命令中使用。还是用个例子说明好了 :

假设你的小说家朋友寄了一本小说的初稿给你,但显然他没有整理文本的习惯——好消息是他这次竟然没用Word写。在你往下看之前你决定先将文档做适当的整理。使用Vim作这种事当然是小菜一碟,只用了10分钟你就将他的小说整理成一份格式整齐的文档了。

第六章 为山九仞
===============

 小明是从不在午时之前离开被褥的,今天却是个例外。他一夜没睡不
 过他却觉得精神比任何时候都好……

 < 省略800行 >
 ……

第七章 功亏一篑
===============

 小明已经很久没像今天这样开心了。从那时到现在已有二十年又一天
 了。对他来讲二十年并不长,能在二十年又三天之内报仇已经是出乎
 自己意料了。何况对方是可是威峦镖局的大当家。想到这里他的眼睛
 眯得更小了……再过两天……只要两天!

但你发现这份初稿没目录,而你看小说的习惯是从目录看起。于是你决定整理一份目录。于是你用了寄存器 :

: let @a = " "
: g /^第.\\{1,3}章 /y A

这两条命令将所有章的标题放到寄存器A中。你可以在需要目录的地方 "a p。不过你还想在每章标题后加上该章对应的行号,你知道这时可以用: redir

: redir @a
: echo "目录:"
: g /^第.\\{1,3}章 /echo getline(".") . "\\t\\t\\t" . line(".")
: redir END

现在你的寄存器a中有了一个带行号的目录了。只用了几行命令你就漂亮地完成任务了,想到这这里你的眼睛眯得更小了……

注 :这里用到的函数是我们在讲折叠时说过的 getline("."),表示返回当前行。 line(".")则返回当前的行号。这两个函数的详细用法见文档。通过对这个脚本进行扩充我们甚至可以让它抓取含小节的目录。

上面的例子演示了通过: redir用户能对寄存器的内容进行进一步的加工而不只是简单的摘录,它增加了寄存器的使用范围。这正是与redir之所以成为寄存器重要性质之一的重要原因。在Vim7.0之前的版本中不支持重定向内容到变量,所以寄存器成了唯一选择。考虑到: redir是比较重要的命令,寄存器吃香也就不足为奇了。但在Vim7开始支持重定向内容到变量后,寄存器就没那么重要了——当然如果你希望方便地将重定向的内容插入到文件中的话寄存器仍是理想之选。关于: redir的更多内容,将会另外解说。

表达式寄存器

虽说是寄存器但从各种角度来看这都是个冒牌的寄存器。它的主要作用是实时计算表达式的值。适用的场合 :在编辑输入时、在命令窗口输入时、在搜索时。使用的方式是按Ctrl - R再按等号(<C - R>=),接着输入表达式,原来输入的位置就会插入表达式的值。只要是合法的表达式都可以使用。我们知道字串可以做为合法的表达式,所以在插入模式下按Ctrl - R =然后输入 "abc"(注意包括 ")当前位置就插入了abc。当然我们不会为了输入字串而使用这个寄存器。现在寄存器a中保存着一个数字,你想在当前文档中搜索该数字4倍的另一个数,你当然不想自己计算。这时使用表达式寄存器:/<Ctrl - R>=@a * 4<Enter>/<Enter> 。其中<Ctrl - R>不是让你输入这8个字符而是按组合键Ctrl - R,同理<Enter>表示这里按了回车。任何时候当你需要插入一个表达式的值时都可以使用这个寄存器。

如果在输入=号后直接按回车没有输入表达式的话默认使用上一次使用的表达式。

在上一个例子中,如果你把刚才的目录贴在文件的开头(当然是开头),会发现行号不准了因为所有的内容都被往下移了——第一行现在变成在目录后面了。假设增加的目录有25行(不知道有几行?:se nu),现在文章的第一行(是空行)成了第26行。当然这样问题难不倒你,让表达式寄存器重新计算一下行号就行了——将原来的行号加上25。

注 :下面几个控制字符的输入方式:^I^R^M,分别表示的是Tab键、Ctrl - R、回车。它们的输入方式是按Ctrl - V(或Ctrl - Q)再输入各自所表示的键。

:1,25 norm $T^I"ty$:s/\[0 - 9\]\\+$/^R = @t + 25^M/^M
  • :1,25 norm:在1到25行之间(目录区)执行一般模式命令。
  • $T^I:移到行末,将光标定位到最后一个制表符后(也就是第一个数字的位置)。
  • "ty$:将数字复制到寄存器t中。
  • :s/\[0 - 9\]\\+$/:将行末的数字(每一章的行号)。
  • ^R =:插入表达式。
  • @t + 25:将寄存器t中的数字加上25。
  • ^M:插入回车结束表达式。
  • /^M:结束s命令并在插入回车键。
  • <Enter>:在全部输入完成后别忘了按回车执行命令。

还有一个特殊的地方可以用上表达式寄存器(Vim文档没说这是一个表达式寄存器,但它的使用方式与表达式寄存器完全一样),就是s命令。:s命令的命令格式为::s/lhs/rhs/,表示搜索lhs并替换为rhs。一个特殊用法就是当rhs的开头为\\`=‘时,这rhs将被视为表达式。lhs将被替换为表达式的值。

  • :将当前行中的算术式'42x31'替换为算术式的结果。
:s/42x31/\\=42 * 31/

再回到刚才的例子中,现在我们可以用一种相对优雅的方式计算更新该目录的行号:

:1,25s/\[0 - 9\]\\+$/\\=submatch(0)+25/

注 :submatch()只在:s命令rhs的表达式中使用。submatch(0)与原来的&在rhs的作用是一样的。submatch(1)就相当于原来rhs中的\\1,依此类推。

创建标记

将光标移到某一行,使用ma命令进行标记。其中,m是标记命令,a是所做标记的名称。

可以使用小写字母a - z或大写字母A - Z中的任意一个做为标记名称。小写字母的标记,仅用于当前缓冲区;而大写字母的标记,则可以跨越不同的缓冲区。例如,你正在编辑File1,但仍然可以使用'A命令,移动到File2中创建的标记A。

跳转标记

创建标记后,可以使用'a命令,移动到指定标记行的首个非空字符。这里'是单引号。也可以使用````a ```命令,移到所做标记时的光标位置。这里```````是反引号(也就是数字键1左边的那一个)。

列示标记

利用:marks命令,可以列出所有标记。这其中也包括一些系统内置的特殊标记(Special marks):

标记 说明
. 最近编辑的位置
0 - 9 最近使用的文件
最近插入的位置
' 上一次跳转前的位置
" 上一次退出文件时的位置
[ 上一次修改的开始处
] 上一次修改的结尾处
删除标记

如果删除了做过标记的文本行,那么所做的标记也就不存在了。我们不仅可以利用标记来快速移动,而且还可以使用标记来删除文本,例如在某一行用ma做了标记,然后就可以使用d'a来删掉这一行。当然,我们也可以使用y'a命令就可以来复制这一行了。

使用:delmarks a b c命令,可以删除某个或多个标记;而:delmarks! 命令,则会删除所有标记。

利用:help mark - motions命令,可以查看关于标记的更多帮助信息。

命令小结
命令 说明
m 创建标记
' 移动到标记的文本行首
``````` 移动到标记的光标位置
:marks 列示所有标记
:delmarks 删除指定标记
:delmarks! 删除所有标记

Vim 常规操作 —— 复制 _粘贴 _剪切 (深入 Vim 寄存器)

大娱乐家 cpy 于 2020-03-28 00:05:12 发布

阅读这篇文章能学到什么?

这篇文章将从 Vim 寄存器的作用角度解答使用 vim 过程中进行复制、粘贴、剪切如何操作的问题。

1. Vim 寄存器

vim 有很多寄存器,我们进行的复制粘贴操作实际就是往这些寄存器写或者读取内容的操作,要想更好的使用复制粘贴功能,需要对这些寄存器有基本的了解。这些寄存器各有其功能,以我现在使用的 gvim_8.2.0318_x64_signed 举例(不排除未来会有版本差异),它具有这么几类寄存器:

  • 无名寄存器 ":缓存最近一次的内容,也是复制粘贴最常用的寄存器;
  • 编号寄存器 0~9:缓存最近操作内容。其中 0 号寄存器有别其他,它缓存最近一次复制的内容,1~9 缓存最近 9 次删除的内容。
  • 命名寄存器 a~z 或 A~Z:指定名称的寄存器,可以由用户自由选择内容缓存进去。要注意的是大小写虽然对应同一个寄存器,但是功能有差异。
  • 只读寄存器 .、:、%:分别缓存上次插入的文本、最近执行的 Ex 命令、当前文件名。
  • 表达式寄存器 =:实际上并不存在这么一个寄存器用来缓存文本,这是方便再使用寄存器的命令中使用表达式的一种方式。该寄存器是可读写的。它缓存的是表达式而不是表达式结果。
  • 轮换文件寄存器 #:内容为当前窗口轮换文件的名字(网上一些文章说将其也归类为只读寄存器是错的,这个寄存器是可写的)。
  • 选择和拖拽寄存器 *、+、:用于与其他应用之间的内容传递交互,是只读的。
  • 最近搜索模式寄存器 /:内容为最近搜索的模式。
  • 行内删除寄存器 -:该寄存器保存删除不到一行的内容,除非刻意指定了用其他寄存器。
  • 黑洞寄存器 _:将内容放入黑洞寄存器不会留缓存记录。

你可以在 vim 中输入指令 reg 查看它的寄存器:

在这里插入图片描述

我们可以看到上面提到的一些寄存器并没有显示出来,但这并不代表它们不存在,比如选择和拖拽寄存器的 + (又称为系统寄存器),它需要你的vim支持 clipboard~ 寄存器需要vim支持 dnd 。而命名寄存器 a~zA~Z 是因为使用大写时操作的依然是对应的小写寄存器,而小写寄存器只有在有内容时才会显示,如果未使用则不会显示。黑洞寄存器是实际并没有用于存储内容的寄存器,它表示的含义就是不将内容放入可以缓存的任何一个寄存器,所以也就能理解为什么没有显示该寄存器。

如何查看自己的vim是否支持clipboard和dnd呢?打开cmd,输入vim --version如果能看到clipboard和dnd前面显示了+则说明支持,如果是-则不支持。不持支的化你可能需要安装支持的版本,或者自己编译vim使其支持,clipboard一般都是支持的,而dnd一般用不到可以不必太在意。

2. Vim复制、粘贴、剪切最基本操作

在进一步学习Vim的寄存器之前我们先学习下Vim的几种基本操作:

必备知识:Vim中y(yank缩写,抽出的意思)键用于复制功能;p(past缩写,放置的意思)键用于粘贴功能;d(delete缩写,删除的意思)键用于剪切功能,因为vim的删除是会在缓存备份的,所以实际就是剪切功能。

  • 常用复制操作:

    • 复制选中的文本:可视模式下选中文本按后y

    • 复制n行:{n}yy{n}Yy{n}y {} 内参数n是可选的,n为从当前行往下数需要复制的行数,当n为1时可省略。

    • 复制到文件末或首:从当前行复制到文件首ygg,从当前行复制到文件尾yG

    • 复制到行首或尾:从光标位置(不包括光标当前所在的字符)复制到行首个字符y^,从光标位置(不包括光标当前所在的字符)复制到行第一列y0。从光标位置(包括光标当前所在的字符)复制到行末y$

  • 常用粘贴操作:

    • 将缓存内容粘贴到光标未知:普通模式下按p
  • 常用剪切操作:

    • 剪切选中的文本:可视模式下选中文本后按d

    • 剪切n行:{n}dd{n}Dd{n}dn为从当前行往下数需要剪切的行数,当n为1时可省略。

    • 剪切到文件末或首:从当前行剪切到文件首dgg,从当前行剪切到文件尾dG

    • 剪切到行首或尾:从光标位置(不包括光标当前所在的字符)剪切到行首个字符y^,从光标位置(不包括光标当前所在的字符)剪切到行第一列y0。从光标位置(包括光标当前所在的字符)剪切到行末y$

前面我们讲到了Vim的多种寄存器可用于缓存内容,那上面这些复制、粘贴、剪切操作用到了哪些寄存器呢?

当没有指定使用某个寄存器时,Vim都会按默认寄存器操作。比如y指令的复制操作默认是将内容缓存在了 " 无名寄存器种,所以粘贴时默认也是将无名寄存器的内容取出。剪切操作的的默认寄存器是 1~9 编号寄存器,这9个寄存器构成了一个“队列”,1号是队尾存放最新剪切掉的内容,当有更新的内容被剪切时小编号内容往大编号移动,最新内容放1号寄存器,超过9号之后就舍去。

用法示例:

使用yy复制整行,观察 " 无名寄存器:

yy 复制整行

在这里插入图片描述

观察 " 寄存器

在这里插入图片描述

使用dd删除 10 行,观察 1~9 编号寄存器的值:

dd 剪切 10 行文本

在这里插入图片描述

观察 1~9 编号寄存器

在这里插入图片描述

3. 如何指定使用某个寄存器

  • 复制操作

    选中要复制的内容,在普通模式下键入指令: "{x}y, {} 内的值是可选的,x代表指定要使用的寄存器。

    举例:要将选中的文本缓存到 a 寄存器则需键入指令: "ay

  • 粘贴操作

    将光标移动要要粘贴的未知,在普通模式下键入指令: "{x}p,同样 {} 内的值是可选的,x代表指定要使用的寄存器。

    举例:要粘贴 a 寄存器的内容则需键入指令: "ap

  • 剪切操作

    vim的删除其实是剪切,删除的同时默认会把内容放进相关的缓存(编号寄存器)。选中要剪切的内容,在普通模式下键入指令: "{x}d。

    举例:要将选中的文本剪切到 + 系统寄存器则需键入指令: "+d

注意:以上的x值并不是指定任意寄存器都能操作成功,比如复制往只读寄存器里缓存内容。剪切操作会按编号寄存器的顺序从1到9传递缓存内容,不能自己打乱。等等。

4. 各寄存器详细讲解

4.1 " 无名寄存器

当使用y相关指令且未指定寄存器时,内容会被填充到无名寄存器中。当使用p相关指令且未指定寄存器时进行粘贴默认取出无名寄存器内容。类似的还有dcsx等和复制或删除相关的指令,在未指定寄存器情况下默认都是使用无名寄存器。无名寄存器用于缓存最近一次进行的复制或剪切内容,即使这定了其他寄存器,无名寄存器也都会被填充最近一次的复制或剪切内容,除非指定的是黑洞寄存器。

用法示例:

使用yy复制文本到 a~zA~Z 命名寄存器,观察 " 无名寄存器内容是否也被修改:

使用命令"ay复制整行到a寄存器,观察 " 寄存器和 a 寄存器值

在这里插入图片描述

从上图可以看出 " 寄存器和 a 寄存器值都发生改变缓存了一份复制内容。

4.2 0~9 编号寄存器

这些寄存器用来存放复制和剪切命令的文本。其中 0 号寄存器用于存放最近复制的文本,而 1~9 号用于存放最近剪切的文本(如果文本少于一行时缓存在行内删除寄存器)。每进行一次剪切操作,Vim会把前一次的寄存器 1 中的内容转存到寄存器 22 又到 3 ,依此类推,到 9 之后就舍弃。也可以指定缓存的寄存器,缓存的内容会被放到指定的寄存器和 1 号寄存器种有

注意:指定寄存器进行剪切时,会先将内容缓存到指定的寄存器,然后又会在 1 号寄存器进行缓存,这是有先后顺序的。比如往 a 寄存器剪切,则内容缓存到 a 寄存器和 1 号寄存器种,但是往 2 号寄存器剪切,内容被缓存到 3 号寄存器和 1 号寄存器,因为缓存 1 号寄存器时编号寄存器内容发生了一次移动。最后,黑洞寄存器依旧是个例外,往黑洞寄存器剪切不会保存内容,即使是 1 号寄存器。

用法示例:

使用"bd指令剪切一行内容到b寄存器,观察 b 寄存器和 1 寄存器值

在这里插入图片描述

从图中可以看出,我们指定寄存器b剪切了一行文本,这行文本的内容总共被缓存到了三个地方, 1 号寄存器、 b 寄存器、 " 无名寄存器。回顾一下前面的无名寄存器,它会自动缓存最近一次的复制或剪切内容,所以就能理解为什么这里进行指定寄存器的剪切操作会缓存到无名寄存器里。

0 号寄存器用于存放最近复制的文本,你可能会发现很不多时候它和 " 无名寄存器的值是相同的,比如对一行文本用yy进行复制。

用法示例:

对一行文本用yy指令进行复制,观察 " 无名寄存器和 0 号寄存器值:

在这里插入图片描述

继续看,对一行文本用dd进行剪切,观察 " 无名寄存器和 0 号寄存器值:

在这里插入图片描述

通过以上对比可知, " 无名寄存器缓存最近一次复制或剪切的内容, 0 号寄存器缓存最近一次复制的内容,而 1~9 号寄存器用于缓存最近9此的剪切内容。所以 " 无名寄存器的值要么等于 0 号寄存器,要么等于 1 号寄存器。

4.3 a~zA~Z 命名寄存器

编号寄存器Vim是不会对其主动操作的,他们是给使用者在编辑过程中自由使用,灵活的使用他们将会使得你的代码编辑最少的敲打重复内容以及调整代码块的位置。这些寄存器在无内容时使用:reg指令不会显示。你可能已经注意到了大小写的问题, aA 是否时两个不同的寄存器?我要告诉你他们都是 a 寄存器,但是产生的效果不同。

用法示例:

对一行文本用"ay指令进行复制,重复两次该操作,观察 a 寄存器值:

在这里插入图片描述

可以看到重复两次操作, a 寄存器也只能保存最新一次的内容。

对一行文本用"Ay指令进行复制,重复两次该操作,观察 a 寄存器值:

在这里插入图片描述

可以看到重复两次操作, a 寄存器保存了多次复制的内容。

所以命名寄存器的大小写指的都是小写寄存器进行存储,但是当使用大写时会把内容进行追加,不会清楚之前保存的内容。利用好大写的命名寄存器可以拼接出我们想要的内容。

注意:其他寄存器Vim对其都有默认的操作,将需要内容保存到其他寄存器会很不安全,因为很可能会Vim自动覆盖,而命名寄存器拥有足够的数量且由用户操作,所以命名寄存器会是我们常用的寄存器。

4.4 . : % 只读寄存器

这些寄存器都是只读的,有其特殊含义所以只能由Vim写。
% 被用于存放当前文件的文件名。

: 缓存最近执行过的命令行,需要注意的是只有当命令中至少有一个字符是键入的,该寄存器才会对指令进行缓存,如果命令行完全来自映射并不会缓存这些指令。这个寄存器需要你的Vim支持 cmdline_hist 特性。

. 在这里插入代码片,寄存器被用于存放最近插入的文本,进入插入模式后输入的内容会被缓存进这个寄存器里,但是不会缓存通过粘贴途径放置的文本。

用法示例:

使用echo @%命令输出 % 寄存器的值。"%p粘贴出 % 寄存器的值:

在这里插入图片描述

可以看到 % 寄存器内的值就是当前文件名

用法示例:

使用:echo "nihao"命令执行一遍字符串输出,然后使用:@:重复执行一次最近执行过的命令。使用":p命令将最近执行的命令内容粘贴出来:

注意Vim的寄存器都可以前面加上@将其当变量使用其值,比如@%和@:。

在这里插入图片描述

用法示例:

使用".p指令粘贴最近一次插入的文本:

在这里插入图片描述

插入一段文本后观察 . 寄存器的值:

在这里插入图片描述

可以看到 . 寄存器将插入文本过程中输入的文本内容和一些退格和换行等信息也保存了,所以粘贴其内容的时候会是完全一样的文本。

注意 . 寄存器和 . 指令不同,Vim重.指令可以将最近的一些操作重复执行,而 . 寄存器是用来缓存最近插入的文本的。一个是指令一个是寄存器,不要搞混了。

4.5 = 表达式寄存器

你可以在插入模式按键ctrl r =将会等待你输入表达式,会在光标处输出表达式的结果(结果自动转换为字符串类型。在普通模式和可视模式下"=同样可执行表达式,不过表达式的结果只有在插入模式下才会输出在光标处。最近使用的表达式会被写入缓存到表达式寄存器(实际并不是一个寄存器,输入表达式时你可以在命令行按上下键选择最近使用过的多条表达式,默认显示最新的表达式)。

用法示例:

使用ctrl r =指令在插入模式下计算表达式并输出值:

在这里插入图片描述

使用指令:reg查看表达式内容:

在这里插入图片描述

注意:如果你无法修改 = 表达式寄存器的值,那很有可能是因为该寄存器被你的插件占用了,比如在插件Neardtree处于打开状态下,该寄存器就会被该插件一直占用,但是不影响插入模式下输出表达式的计算结果。

4.6 # 轮换文件寄存器

这个寄存器也是在没有值时:reg指令下并不会显示它。它的值为当前窗口轮换文件的名字,你可以简单的理解为“上一次打开的文件的相对路径(这个相对路径不是指相对当前文件,是相对Vim的当前所处目录”,为什么要叫轮换文件寄存器呢?因为可以使用指令ctrl ^在当前文件和上一次文件之间来回切换。

用法示例:

使用"#p指令粘贴 # 轮换文件寄存器值:

在这里插入图片描述

使用reg查看 # 轮换文件寄存器值:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ejVpipfI-1585324490702)在这里插入图片描述

4.7 *、+、~ 选择和拖拽寄存器

~ 寄存器是只读的,它缓存最近一次拖放操作放下的文本。比如你从其他地方鼠标选中一段文本将其直接拖入Vim界面,这时候这些文本就会被缓存到 ~ 寄存器里。需要你的vim支持 dnd 才可使用此寄存器。 + 寄存器就是我们常说的系统寄存器,用于和外界内容的拷进拷出。在MS-Windows上, *+ 寄存器是等价的,而在X11系统上有区别。

4,8 / 最近搜索模式寄存器

将最近的搜索模式缓存入该寄存器,实际不止缓存一条内容,它可以缓存最近使用过的搜索模式,普通模式下按/后可通过鼠标上下键选择。

用法示例:

使用/nihao指令进行模式搜索后,使用"/p指令粘贴最近使用过的模式匹配内容:

在这里插入图片描述

使用:reg指令查看 / 最近模糊模式寄存器

在这里插入图片描述

4.9 - 行内删除寄存器

在行内进行删除时(删除的内容未达到一行),内容默认保存到 - 行内寄存器下。如果指定缓存在别的寄存器下时,内容只会被缓存到指定的寄存器,不会改变 - 行内寄存器的值。

用法示例:

使用指令"ad"删除行内一段文本后,使用指令:reg查看寄存器值变化:

在这里插入图片描述

删除的行内内容放入指定寄存器a,且 - 行内寄存器值并未改变。当然 " 无名寄存器的值也会被改变。

4.10 _ 黑洞寄存器

将内容指定放入 _ 黑洞寄存器就意味着不放入任何其他寄存器。当你想彻底删除某些内容而不影响其他寄存器时就可以指定其放入 _ 黑洞寄存器。

用法示例:

使用指令"_d删除一行文本”1010101010“,观察各个寄存器值变化:

在这里插入图片描述

可以看到,指定放入 _ 黑洞寄存器的内容不会改变其他任何寄存器的值。


via: