Vim常規操作——複製_粘貼_剪切(深入Vim寄存器)

Vim常規操作——複製_粘貼_剪切(深入Vim寄存器)

1. 閱讀這篇文章我能學到什麼?
你可能想知道其他軟件與vim之間,vim與其命令行之間如何進行復制、粘貼、剪切問題,那麼就請閱讀這篇文章。這篇文章將從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~z或A~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“,觀察各個寄存器值變化:
在這裏插入圖片描述
可以看到,指定放入 _ 黑洞寄存器的內容不會改變其他任何寄存器的值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章