透過 vi 編輯器在純 CLI 環境下編輯文字檔案

8 min

vi 是一個極度輕量且包含許多基礎功能的文字編輯器,通常預設安裝在大多數 Unix 系統中,像是 Ubuntu 或 macOS 都有內建 vi 編輯器,為了在只有 CLI 介面的系統上靈活地修改文字檔案,學會使用 vi 編輯器是非常重要的。

開始使用

要使用 vi 編輯器,你需要在終端機中輸入以下指令:

vi [options] [file(s)]

這會開啟 vi 編輯器,使你能透過下方的流程對檔案進行編輯,接下來就讓我們看看進入 vi 編輯器後實際上能做些什麼。

flowchart TD
    Start([Start vi]) --> Command[Command Mode]
    
    Command -->|"/ ?"| Other[Other Commands]
    Other -->|Enter| Command
    
    Command -->|":"| Last[Last Line Mode]
    Last -->|"wq"| End([End vi])
    Last -->|"q!"| End
    Last -->|"q"| End
    
    Command -->|"i,a,o,r,c"| Insert[Insert Mode]
    Insert -->|Esc| Command
    Command -->|"ZZ"| End

Command Mode

如上面流程圖所示,進入 vi 編輯器後會直接進到 Command Mode,在這個模式下可以透過各種指令來做到移動游標編輯文字複製貼上進入 Insert Mode進入 Last Line Mode 等功能。

而這些指令會以下面的語法呈現:

[要執行幾次 operation] operation [要作用在幾個 target 上] target

移動游標

可以透過 Ctrl + G 來查看目前游標所在位置,以下是一些常用的游標移動指令:

Command動作
1Ggg移到第一行的第一個 character
G移到最後一行的第一個 character
L移到畫面上最後一行的第一個 character
^移到 current line 的第一個非空白的 character
0移到 current line 的第一個 character
$移到 current line 的最後一個 character
w移到下一個 word 的第一個 character
b移到上一個 word 的第一個 character
}移到下一個 paragraph

編輯文字

Command意義動作
dddelete刪除 current line
7dddelete刪除 current line 及向下 6 個 lines (總共刪 7 lines)
d$Ddelete把 cursor 所在位置及以後的 characters 全部刪掉
5dwdelete刪 5 words
xdelete刪除 cursor 指著的 chararcter
Xdelete刪除 cursor 前一位的 character
uundo返回上一個動作

複製貼上

Command動作
y2W從目前 cursor 位置向右複製兩個 words
4yb從目前 cursor 位置向左複製四個 words
yyY複製目前這一行
p將被複製的文字放到目前 cursor 位置之後
P將被複製的文字放到目前 cursor 位置之前
5p將 buffer 中的被複製的文字放到目前 cursor 位置之後五次
Y複製目前這一行
yy複製目前這一行
" x yy複製目前這一行到 register x
ye複製到 word 結尾
yw類似 ye,但包含 word 後面的空白
y$複製該行剩餘部分
" x dd刪除目前這一行並存入 register x
" x d刪除並存入 register x
" x p放入 register x 的內容
y]]複製到下一個 section heading
J將目前這一行與下一行合併
gJ類似 J,但不插入空格(vim 和 gvim)
:j類似 J
:j!類似 gJ

進入 Insert Mode

Command意義動作
aappend在 cursor 後面新增字
Aappend在 current line 最後一個字後面新增字
cwchange開啟 replace mode 直至目前 cursor 所在的 word 的結尾
ccchange把 current line 整個刪掉後進入 insert mode
c$Cchange開啟 replace mode 直至 current line 的最後一個字
iinsert在 cursor 前面新增字
Iinsert在 current line 第一個字前面新增字
oopen在 current line 下面開一個新的 blank line 並把 cursor 放到那行上
Oopen在 current line 上面開一個新的 blank line 並把 cursor 放到那行上
Rreplace進入 replace 模式,輸入的字會覆蓋 cursor 在的字
ssubstitutereplace 一個 character 後進入 insert mode
Ssubstitute先把整行的內容刪掉之後進入 insert mode

進入 Last Line Mode

直接輸入 : 就可以進入 Last Line Mode。

Insert Mode

如其名,就是輸入文字的模式,在這個模式下你可以像一般文字編輯器一樣輸入文字,當你想要回到 Command Mode 時,只需要按下 Esc 鍵即可。

Last Line Mode

檔案相關

Command動作
: n, m w file將第 n 行到第 m 行寫入新檔案
: n, m w >> file將第 n 行到第 m 行附加到現有檔案
:r filename在目前 cursor 位置讀取並插入 filename 的內容
:wq儲存 buffer 並離開
:w儲存目前 buffer 並留在 editor 中
:w filename將目前 buffer 儲存到 filename
:w! filename以目前內容覆寫 filename
:w!強制寫入檔案(覆蓋保護)
:w! file以目前內容覆寫 file
:w %.new將目前 buffer 寫入名為 file.new 的檔案
:q離開 vi(如果有修改過會失敗)
:q!不儲存 buffer 直接離開 vi
:Q離開 vi 並啟動 ex
:vi在 Q 指令後返回 vi
ZZ離開 vi,僅在上次儲存後有修改時才儲存檔案
%在編輯指令中代表目前的 filename
#在編輯指令中代表替代的 filename

取代與搜尋

Command動作
:s/john/jane/在目前這一行將 john 替換為 jane,僅一次
:s/john/jane/g在目前這一行將每個 john 都替換為 jane
:1,10s/big/small/g在第 1 到第 10 行將每個 big 都替換為 small
:1,$s/men/women/g在整個檔案中將每個 men 都替換為 women
:'<,'>s/this/that/g先在 Command mode 中按 <Ctrl+V> 並使用方向鍵選取範圍,然後輸入 :this 替換為 that(僅限 vim、gvim)
:s/ \<tim\>/tom/僅替換完整的單字 timtom,而非字串中部分匹配的 tim
:%s/terrible/wonderful/gc使用 c 選項進行互動式替換,將 terrible 替換為 wonderful(僅限 vim、gvim)
:%s/^/ \=line(".") . ". "/g將 buffer 中所有行的行號永久加到每行開頭(僅限 vim、gvim)

環境設置

設置縮寫

Command動作
:ab in out在 Insert mode 中將 in 作為 out 的縮寫
:unab in移除 in 的縮寫
:ab列出所有縮寫

設置映射

Command動作
:map string sequence將字元字串映射為一連串指令。使用 #1、#2 等代表 function keys
:unmap string移除字元字串的映射
:map列出已映射的字元字串
:map! string sequence將字元字串映射為 input mode 的指令序列
:unmap! string移除 input mode 的映射(可能需要用 <Ctrl+V> 來引用字元)
:map!列出 input mode 中已映射的字元字串
qx將輸入的字元錄製到指定字母 x 的 register 中(vim 和 gvim)
q停止錄製(vim 和 gvim)
@x執行指定字母 x 的 register。使用 @@ 重複上一個 @ 指令

設置選項

Command動作
:set x啟用 boolean option x,顯示其他 options 的值
:set nox停用 option x
:set x=value設定 option x 的值
:set顯示已變更的 options
:set all顯示所有 options
:set x?顯示 option x 的值
TIP

如果想永久保存這些環境設定,可以將想設定的指令寫入 .exrc 中。