我們在講到的時候,內文提到了一個 然後按 / 就可以叫出用 / 作搜尋時所打的字串。這種呼叫出之前打過的字的方式,就是本次的主角 register。

按照 vim help 上面的說明,vim 提供的 registers(暫存器)有下列幾種:

  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. four read-only registers “:, “., “% and “#
  6. the expression register “=
  7. The selection and drop registers “*, “+ and “~
  8. The black hole register “_
  9. Last search pattern register “/

雖然看上去有九種之多,但經常會用的並不多。

在 vim 裡面,為了方便使用者可以少打點之前已經打過的字串,或是因為某些理由,設置了因應不同需求的暫存空間,而且這些暫存空間其實都是有它的意義存在。舉例來說,像前面說的 / 就是用到「/」這個暫存器裡面的內容。簡單地說你可以用 在命令模式要打指令的時候使用。或是在作貼上(p)動作的時候指定暫存器的內容(”[0-9a-z/%])等等。我們現在還是從實例開始談起。

Register 0:

讓我們來想像一個情境:

當你會使用選擇模式(visual mode)或是用 yank的方式(vy)把該區域貼上,當你要用的時候,很自然地你會使用 p 這個指令把你要的東西貼上。

但是往往在編輯的時候,打錯一些東西,你就刪除 了某些字或行。真糟,如果你再用 p ,那麼貼上的就是你剛剛刪掉的那些字或行。如果我要用剛剛 yank 或是進 visual mode 所 copy 的東西怎麼辦?難道還要再一次?真麻煩…

別耽心, register 0 就是幫你把最近一次做 yank 動作所存進去的東西。所以如果你還要用到剛剛才 yank 的東西,那你只要按下

“0p

就代表要貼上最近一次 yank 的東西。

Registers [1-9] :

那 “[1-9]這些這些暫存器的功能又和 0 不一樣。[1-9]他們之間的關係是當你刪了某些字行的時候,這個被刪的字或行,會進入 “1 這個 register ,當你又刪了的時候,這次被刪的東西的會進入 “1 ,那原來在 “1 的東西就會被放到 “2 去。依此類推。那這個有什麼用呢?因為我怎麼可能會去記我第幾次刪掉的東西會是什麼?沒關係,這裡有個小指令,可以讓你看到那些 register 裡面到底放了什麼?

:di

這就會把所有 register 到底放些什麼東西秀出來給你看。如果你懶得去 :di 一個個看的話,也有別的方法,就是直接貼出來看:

“1p

你會想,這很直覺啊。但是你發現它不是你要的東西的時候怎麼辦?直覺的想法是 u ,我 undo 就好了嘛。問題是,要貼出下一個暫存器內容的時候你打算怎麼辦? “2p 嗎?非也。而是「 . 」,當你按下「 . 」的時候 vim 就會把 “2 的內容貼出來,依此類推,只要東西真的存在你的”[1-9] 暫存器裡面,你就一定會找到它。好吧,這個有點奇技淫巧了,因為你可能願意用 :di 看了之後再貼。

其他的 registers:

而 a-z A-Z 這些 reigster 是你指定才會用到的東西。什麼意思呢?也就是說你必須指定暫存器[a-zA-Z]和要放進去的內容才會在 :di 中出現。

一個簡單的指定方法像是在 command line 下打:

:let @a=”Hello, world”

則 “a 這個 register 就會被放入 Hello, world 這個字串。所以如果你想把某個暫存器裡面資料清除掉的話,也可以用:

:let @a=”"

你也可以像之前我們在談的 visual mode,選取範圍之後指定暫存器 “[0-9a-z] 來存放。不過由於 “[0-9] 有特殊的關係,可能會被覆蓋,所以我個人會建議你使用 “[a-z]。

或許細心的讀者會發現不是明明可以指定 [a-zA-Z] 嗎?為什麼這邊只談到 [a-z]?這是因為大寫的 [A-Z]有特殊的意義。

當你指定 “[a-z] 暫存器來使用的時候,事實上是把指定的內容覆蓋上去。但是如果你想要的是附加而不是覆蓋呢?那就得使用 “[A-Z] 了。比方說,我們之前的時候,有提到怎麼樣只顯示出包含搜尋字串的行。可是如果你想要把這些東西放進去暫存器留待下次使用的話怎麼辦?

一般來說 :g 的運作方式是根據一行一行來做的,簡單地說,當你用下面指令的時候,

:g/pattern/y a

這代表的意思其實只是把每次比對到的那行都 yank 複製到 “a 這裡面去。所以這就會造成我們最後只會拿到最後一行的結果,而不是每個比對到的都會進入到 “a 去。所以就必須告訴 vim 我們指定的內容是要做附加而不是覆蓋:

:g/pattern/y A

附帶一提:所以如果你想要把這些東西寫到某個檔案去可以這樣寫:

:g/pattern/. w >> filename

基本上你可以指定暫存器內容的有 [1-9a-zA-Z] 這些,其他的有些也可以,像是 0 ,但是因為這類暫存器都有它的特殊功用,所以我不太建議你指定內容給他們。

回到暫存器存在的目的,其實就是為了讓大家少打一些字。像是如果我今天從某個地方 copy 複製了一段文字,想要放到 vim 現在正在編輯的文件裡面。在 windows 上的 vim 你可以用幾種方法,第一個很簡單就是用 gvim ,用滑鼠按貼上的按鍵,另外一個就是用 windows 的熱鍵 ,不過我們可以用很 vim 的方式來做。在 vim 要叫出暫存器的內容有 +暫存器名稱,或是以 “(暫存器名稱)p 來貼。比方說我現在用 visual mode 選取一個區域,我想要把系統「剪貼簿」上的東西來取代選取的區域,就可以在選取好之後,用

“*p

就可以把剛剛的部分換成在系統「剪貼簿」裡面的東西。

如果你是在編輯模式下的話,「“*」這些字都會被打出來,所以就必須透過

*

來把內容叫出來。所以到這裡不必我說,你也知道 “* 指的就是系統「剪貼簿」裡面的內容。另外像是 “: 就是指打的命令的暫存器,同樣之前提過的 “/就是放搜尋的字串。其他像是 “. 放最近 insert 插入的文字,“- 放砍掉但不超過一行的文字,或是 “% 指現在編輯的檔名,都不見得常用。雖然有時候如果你想存個現在檔案的備份可以這樣寫而少打幾個字:

:w %.bak

不過有個東西可以稍微提一下,就是 “_ (黑洞暫存器),如果你刪除的動作不想要牽涉到任何暫存器的話,那你就可以用 “_。比方我可以用:

v”_x

就不會改到其他的暫存器。

如果你對其他的暫存器或是想知道更詳盡的資料可以打

:h registers