使用 evil 之前,得了解 vi/vim 的一些基本常識。
命令模式下的遊標是一個方塊,它的當前位置是指塊的最左邊。下圖中當前遊標所在位置是兩個 e 的中間。
文章目錄
模式
命令模式(執行管理任務)
- 所輸入的內容被解釋成命令,功能包括
- 保存文件、執行命令
- 移動遊標、剪切、粘貼多行或多個單詞、查找、替換
- 所輸入的任何字符被解釋成命令
- 命令模式包含
末行模式
(last line mode/指令列命令模式)
末行模式
末行模式在命令模式下輸入 :
進入。由於此時光標移動到最後一行,因此得名。
插入模式(向文件中輸入文本)
鍵入所有內容被認爲是文本輸入。
在命令模式下輸入以下命令將進入插入模式。沒有進入插入模式的會註明。
命令 | 結果 |
---|---|
i | 在當前遊標位置之前 插入文本 |
I | 在當前行的開始處 插入文本(非空字符的行首) |
a | 在當前遊標位置之後 插入文本 |
A | 在當前行的結尾處 插入文本 |
o | 在當前行下面新建一行 |
O | 在當前行的上面新建一行 |
s | 刪除遊標後 的一個字符 |
S | 刪除遊標所在的行(刪除當前行) |
r | 替換(覆蓋)當前遊標位置之後的一個字符,然後進入命令模式 |
R | 替換(覆蓋)當前遊標位置及後面的若干文本(進入替換模式 ) |
cc | 刪除當前行內容 |
cw | 刪除遊標所在位置到單詞末尾 |
ch | 刪除遊標位置之前的一個字符 |
cl | 刪除遊標位置之後的一個字符 |
cj | 刪除當前行和下一行 |
ck | 刪除當前行和上一行 |
提醒,想在下圖行末加個空格時,命令模式下移到最後一個字符,再鍵入 a
(原來沒做這個總結時,不知道有向後插入的命令,我都是先鍵入 i,再 C-e 到最後的,邊摁邊想這也太麻煩了。現在再想真的太羞恥了 😒
當然也可以直接 A
可視模式
這個一開始不必掌握,而且能在命令模式下解決的就儘量不進入可視模式解決(使用 C-v 真的很方便)
在命令模式下輸入以下命令進入可視模式
命令 | 結果 |
---|---|
v | 逐個字符選擇文本 |
V | 逐行選擇文本 |
C-v | 按照塊的方式選擇文本(忽視行,可以理解爲面向列) |
gv | 重選上次的高亮區域 |
高亮選區由兩個端點確定:一個固定的端點,一個活動的端點。
字符 o
可以在不同的的端點之間來回的切換。
其中塊選中的理解可以參考 cmd 下選中文本塊。
當我們選中了一片高亮區域後,可以使用如下命令對高亮區域進行操作:
命令 | 效果 |
---|---|
d | 剪切選中文本 |
c | 修改選中文本 |
r | 替換選中文本 |
I | 在選中文本前插入 |
A | 在選中文本後插入 |
gu | 選中區域轉爲小寫 |
gU | 選中區域轉爲大寫 |
g~ | 大小寫互調 |
> | 向右縮進一個單位 |
< | 向左縮進一個單位 |
比如我有如下這個文本,我想把它快速轉化成列表,就可以用到 C-v 命令
在第四行 C-v 進入可視模式後,使用 k 向上移動到第一行。我們再鍵入 c
刪除選中列,再輸入 .
,最後鍵入 Esc 退出。就可以看到結果了。
模式間的切換
任何模式下使用 ESC
將退回到命令模式,實在不行摁兩下。
移動1
因而,在使用命令進行操作的時候,首先要搞清楚的就是要採用哪種操作單位,也就是說,是要操作一個字符,一個句子,一個段落,還是要操作一行,一屏、一頁。單位不同,命令也就不同。只要單位選用得當,命令自然就恰當,操作也自然迅速高效;否則,只能是費時費力。這也可以說是最能體現 Vi/Vim 優越於其它編輯器的地方之一,也是 Vi/Vim 有人愛有人恨的地方之一。
在操作單位確定之後,纔是操作次數,即確定命令重複執行的次數。要正確高效的運用 Vi/Vim 的各種操作,一定要把握這一原則:先定單位再定量
。操作對象的範圍計算公式爲:操作範圍 = 操作次數 * 操作單位。比如:5h 命令左移 5 個字符,8w 命令右移 8 個單詞。
操作單位 | 命令 | 效果 |
---|---|---|
字符 | h l |
左移一個字符 右移一個字符 |
單詞 | w/W b/B e/E |
移到下一單詞的開頭 移到上一單詞的開頭 移到光標所在單詞末尾 |
行 | j k 0 ^ g_ $ :n nG n+ n- |
下移一行 上移一行 移到當前行開頭 移到當前行的首個非空字符 移到當前行末尾 移到當前行末尾 移動到第 n 行 移動到第 n 行 從光標當前行下移 n 行 從光標當前行上移 n 行 |
句子 | ) ( |
移動到當前句子 的末尾 移動到當前句子的開頭 |
段落 | } { |
移動當前段落的末尾(下一個有空行的地方) 移到當前段落的開頭(上一個有空行的地方) |
屏 | H M L |
遊標移動到屏幕的第一行 遊標移動到屏幕的中間一行 遊標移動到屏幕的最後一行 |
頁 | C-f C-b C-u C-d zz |
向前滾動一頁 向後滾動一頁 向前滾動半頁 向後滾動半頁 當前行居中 |
文件 | G gg :0 :$ |
移動到文件末尾 移動到文件開頭 移動到文件第一行 移動到文件最後一行 |
說明:
- W、B、E 命令操作的單詞是以空白字符(空格、Tab)分隔的字串
比如字符串 “str1-str2 str3-str4”
對 W、B、E 命令來說是兩個單詞
而對 w、b、e 命令來說則是四個單詞。 - 0 爲數字零(zero)
- 句子指以 ”.”、”?” 和 ”!” 結尾,後面至少有一個空格或換行符的字符串
複製、粘貼和刪除
以下命令都是在命令模式下進行,並且執行之後還在命令模式
複製
操作單位 | 命令 | 效果 |
---|---|---|
字符 | yl/vy(visual yank) | 複製當前字符 |
單詞 | yiw | 複製當前單詞 |
行 | yy | 複製當前行 |
- yl 複製單個字符(好像只支持 ASCII,具體討論可以看給出的鏈接)
- yiw 複製整個單詞
- yaw 複製整個單詞(帶空格)
- yw 複製遊標所在單詞的後半部分
- yy 複製整行
- 3yy 複製含當前行在內的下三行
- yap 複製整個自然段(包括換行符)
剪切
操作單位 | 命令 | 效果 |
---|---|---|
字符 | x X |
剪切遊標位置後一字符(相當於 DELETE) 剪切遊標位置前一字符(相當於 BACKESPACE) |
單詞 | dw (更多參考上面的 yank) | 剪切當前遊標位置至下一個單詞前的字符 |
行 | dd D d0 d$ |
剪切遊標所在的行 從遊標位置開始剪切到行尾 從遊標位置剪切至行首 從遊標位置剪切至行尾 |
用 v 進入可視模式後,選中文本之後可以按 y 進行復制,如果按 d 就表示剪切。
粘貼
命令 | 說明 |
---|---|
p | 將複製的單詞粘到遊標後面 複製後的行粘到遊標所在行下面 |
P | 將複製的單詞粘貼到遊標前面 複製後的行粘到遊標所在行上面 |
刪除
刪除後改變當前模式的命令可以參考 插入模式
小節
操作單位 | 命令 | 效果 |
---|---|---|
字符 | x X |
剪切遊標位置後一字符(相當於 DELETE) 剪切遊標位置前一字符(相當於 BACKESPACE) |
單詞 | dw | 剪切當前遊標位置至下一個單詞前的字符 |
行 | dd D d0 d$ J |
剪切遊標所在的行 從遊標位置開始剪切到行尾 從遊標位置剪切至行首 從遊標位置剪切至行尾 合併遊標所在行及下一行爲一行 |
其他命令
功能 | 命令 | 效果 |
---|---|---|
重複操作 | . |
重複上次操作 |
交換相鄰字符或行 | xp ddp |
交換光標位置的字符和它右邊的字符 交換光標位置的行和它的下一行 |
大小寫轉換 | ~ guw gUw guu gUU g~~ |
將光標下的字母大小寫反向轉換 將光標所在的單詞變爲小寫 將光標所在的單詞變爲大寫 光標所在的行所有字符變爲小寫 光標所在的行所有字符變爲大寫 光標所在的行所有字符大小寫反向轉換 |
搜索和替換
搜索
下面的 前 是指 h 的方向
命令 | 說明 |
---|---|
/ | 從當前位置向後搜索 |
? | 從當前位置向前搜索 |
n | 搜索下一個 |
N | 反向搜索下一個 |
* | 在文件中向後搜索當前光標所在的單詞 |
# | 在文件中向前搜索當前光標所在的單詞 |
顯示搜索歷史
q/
或 q?
替換
命令 | 說明 |
---|---|
:s/被換單詞/新單詞/ | 替換光標所在行的第一個被換單詞 |
:s/被換單詞/新單詞/g | 替換光標所在行的全部被換單詞 |
:x,ys/被換單詞/新單詞/ | 在x和y行之間替換每一行的第一個被換單詞 |
:x,ys/被換單詞/新單詞/g | 在x和y行之間替換全部被換單詞 |
:%s/被換單詞/新單詞/ 替換每一行的第一個被換單詞
:%s/被換單詞/新單詞/g 替換每一行中所有被換單詞
如果我們想要替換的字符串中包含 / 怎麼辦呢?
此時我們可以使用分隔符 # 來代替 分隔符 /
:s#vivian/#sky/#
替換當前行第一個 vivian/ 爲 sky/
:%s+/oradata/apras/+/user01/apras1+
(使用 + 來 替換 / )
將 /oradata/apras/ 替換成 /user01/apras1/
爲了防止替換錯了,我們可以在替換前加個提醒
:1,$s/misspelled/spelled correctly/gc
:1,$s/misspelled/spelled correctly/c
c 確認後再替換
標籤
使用 m
創建,`(ESC 下面的那個鍵)訪問。
比如 m a
創建一個叫做 a 的標籤,然後使用 ` a 到達該行。
當然這個只能是在同一個文件內,並且關閉文件再打開後得重新創建。
- 如果標記的太多了,記不住標記了哪些的話,可以嘗試使用 package evil-visual-mark-mode
- 如果想保存設置的標籤,可以嘗試使用 desktop.el 保存,參考 How to Persist Evil Markers?
撤銷
命令模式下
u
撤銷上一次編輯U
當前行
恢復到原始狀態(撤銷對本行的所有操作)C-r
反反撤銷
重複命令
在命令模式輸入命令之前,可以先輸入一個數字,表示想要執行接下來輸入的命令的次數。
- 10j 下移10行
- 10l 右移10個字符
- 6h 左移6個字符
- 3dd 刪除三行
退出
命令 | 說明 |
---|---|
:q | 如果修改文件,vi詢問用戶是否保存文件,不保存則退出vi,否則不能退出。 |
:w | 保存當前文件。如果用戶對當前文件沒有寫權限,不能保存文件並收到一條錯誤消息。 |
:wq | 保存並退出,與:wq相同 |
:q! :w! :wq! |
!表示直接執行命令,不提供保護措施,不考慮命令是否執行成功。 |
ZZ | 保存並退出,與:wq相同 |
ZQ | 無條件退出,與:q!相同 |
:x | 保存並退出 |
:w filename | 將編輯內容另存到文件 filename 中。啓動vi時未指定文件名,須用此命令保存編輯內容到文件中 |
:m,nw filename | 將 m 行到 n 行部分的內容保存到文件 filename 中 |
:m,nw >> filename | 將 m 行到 n 行的內容添加到文件 filename 的末尾 |
:e! | 打開文件的上一次成功保存的版本。 |
總結
下圖來自 vi/vim 基本使用方法,侵刪。
參考
Vim 技巧之四大模式_可視模式
linux:vi 替換命令
Linux—vi/vim 複製剪切粘貼以及常用命令小結
補充
這篇文章我感覺有些因小失大了,我自己常用的命令翻來覆去也就 j k dd c-v ~ 那麼幾個。反而這段時間無意中嘗試到了幾個更加有用的,原來壓根不知道的快捷鍵:
-
C-c p
(evilnc-comment-or-uncomment-paragraphs):快速註釋某一段代碼
原來我都是C-@
然後 j k 選中要註釋掉的區域,運行M-x comment/uncomment region
的,無意間發現這個命令心情真是久久難以平復。 -
C-c l
(evilnc-quick-comment-or-uncomment-to-the-line):Comment/uncomment to line number by last digit(s) whose value is UNIT (這個不太理解) -
如果寫 lisp 程序的話,如下幾個處理括號的命令你一定不能錯過,來自
ci(
刪除這對括號裏的所有內容(不包括這對括號)va(
選中這對括號在內的所有內容(包括這對括號)%
在這對括號之間移動
如果你對在 evil 的 insert mode 移動感到不滿的話,或許 Traversing text in Insert mode 這篇帖子和 Evil Mode best practice 會對你有所啓發。
至於如果找到更多有用鍵位,我還不太清楚。大概是 evil-collection 吧。
TODO
技巧:快速提高 Vi/Vim 使用效率的原則與途徑
Vi/Vim 中很多命令是針對不同的操作單位而設的,不同的命令對應不同的操作單位。 ↩︎https://vi.stackexchange.com/questions/5806/how-can-i-yank-copy-the-single-character-on-which-the-cursor-rests ↩︎