鳥哥的 Linux 私房菜
<<

第九章、vim 程式編輯器

最近更新日期:2015/07/07

系統管理員的重要工作就是得要修改與設定某些重要軟體的設定檔,因此至少得要學會一種以上的文字介面的文書編輯器。 在所有的 Linux distributions 上頭都會有的一套文書編輯器就是 vi ,而且很多軟體預設也是使用 vi 做為他們編輯的介面, 因此鳥哥建議您務必要學會使用 vi 這個正規的文書編輯器。此外,vim 是進階版的 vi , vim 不但可以用不同顏色顯示文字內容,還能夠進行諸如 shell script, C program 等程式編輯功能, 你可以將 vim 視為一種程式編輯器!鳥哥也是用 vim 編輯鳥站的網頁文章呢! ^_^

9.1 vi 與 vim

由前面一路走來,我們一直建議使用文字模式來處理 Linux 系統的設定問題,因為不但可以讓你比較容易瞭解到 Linux 的運作狀況,也比較容易瞭解整個設定的基本精神,更能『保證』你的修改可以順利的被運作。 所以,在 Linux 的系統中使用文字編輯器來編輯你的 Linux 參數設定檔,可是一件很重要的事情呦!也因此呢,系統管理員至少應該要熟悉一種文書處理器的!

Tips鳥哥的圖示 這裡要再次的強調,不同的 Linux distribution 各有其不同的附加軟體,例如 Red Hat Enterprise Linux 與 Fedora 的 ntsysv 與 setup 等,而 SuSE 則有 YAST 管理工具等等, 因此,如果你只會使用此種類型的軟體來控制你的 Linux 系統時,當接管不同的 Linux distributions 時,呵呵!那可就苦惱了!

在 Linux 的世界中,絕大部分的設定檔都是以 ASCII 的純文字形態存在,因此利用簡單的文字編輯軟體就能夠修改設定了! 與微軟的 Windows 系統不同的是,如果你用慣了 Microsoft Word 或 Corel Wordperfect 的話,那麼除了 X window 裡面的圖形介面編輯程式(如 xemacs )用起來尚可應付外,在 Linux 的文字模式下,會覺得文書編輯程式都沒有視窗介面來的直觀與方便。

Tips鳥哥的圖示 什麼是純文字檔?其實檔案記錄的就是 0 與 1 ,而我們透過編碼系統來將這些 0 與 1 轉成我們認識的文字就是了。 在第零章裡面的資料表示方式有較多說明,請自行查閱。 ASCII 就是其中一種廣為使用的文字編碼系統,在 ASCII 系統中的圖示與代碼可以參考 http://zh.wikipedia.org/wiki/ASCII呢!

那麼 Linux 在文字介面下的文書編輯器有哪些呢?其實有非常多喔!常常聽到的就有: emacs, pico, nano, joe, 與 vim 等等(註1)。 既然有這麼多文字介面的文書編輯器,那麼我們為什麼一定要學 vi 啊?還有那個 vim 是做啥用的?底下就來談一談先!

9.1.1 為何要學 vim

文書編輯器那麼多,我們之前在第四章也曾經介紹過那簡單好用的 nano ,既然已經學會了 nano ,幹嘛鳥哥還一直要你學這不是很友善的 vi 呢?其實是有原因的啦!因為:

  • 所有的 Unix Like 系統都會內建 vi 文書編輯器,其他的文書編輯器則不一定會存在;
  • 很多個別軟體的編輯介面都會主動呼叫 vi (例如未來會談到的 crontab, visudo, edquota 等指令);
  • vim 具有程式編輯的能力,可以主動的以字體顏色辨別語法的正確性,方便程式設計;
  • 因為程式簡單,編輯速度相當快速。

其實重點是上述的第二點,因為有太多 Linux 上面的指令都預設使用 vi 作為資料編輯的介面,所以你必須、一定要學會 vi ,否則很多指令你根本就無法操作呢!這樣說,有刺激到你務必要學會 vi 的熱情了嗎? ^_^

那麼什麼是 vim 呢?其實你可以將 vim 視作 vi 的進階版本,vim 可以用顏色或底線等方式來顯示一些特殊的資訊。 舉例來說,當你使用 vim 去編輯一個 C 程式語言的檔案,或者是我們後續會談到的 shell script 腳本程式時,vim 會依據檔案的副檔名或者是檔案內的開頭資訊, 判斷該檔案的內容而自動的呼叫該程式的語法判斷式,再以顏色來顯示程式碼與一般資訊。也就是說, 這個 vim 是個『程式編輯器』啦!甚至一些 Linux 基礎設定檔內的語法,都能夠用 vim 來檢查呢! 例如我們在第七章談到的 /etc/fstab 這個檔案的內容。

簡單的來說, vi 是老式的文書處理器,不過功能已經很齊全了,但是還是有可以進步的地方。 vim 則可以說是程式開發者的一項很好用的工具,就連 vim 的官方網站 (http://www.vim.org) 自己也說 vim 是一個『程式開發工具』而不是文書處理軟體~^_^。 因為 vim 裡面加入了很多額外的功能,例如支援正規表示法的搜尋架構、多檔案編輯、區塊複製等等。 這對於我們在 Linux 上面進行一些設定檔的修訂工作時,是很棒的一項功能呢!

Tips鳥哥的圖示 什麼時候會使用到 vim 呢?其實鳥哥的整個網站都是在 vim 的環境下一字一字的建立起來的喔! 早期鳥哥使用網頁製作軟體在編寫網頁,但是老是發現網頁編輯軟體都不怎麼友善,尤其是寫到 PHP 方面的程式碼時。 後來就乾脆不使用所見即所得的編輯軟體,直接使用 vim ,然後標籤 (tag) 也都自行用鍵盤輸入! 這樣整個檔案也比較乾淨!所以說,鳥哥我是很喜歡 vim 的啦! ^_^

底下鳥哥會先就簡單的 vi 做個介紹,然後再跟大家報告一下 vim 的額外功能與用法呢!


9.2 vi 的使用

基本上 vi 共分為三種模式,分別是『一般指令模式』、『編輯模式』與『指令列命令模式』。 這三種模式的作用分別是:

  • 一般指令模式 (command mode)

以 vi 打開一個檔案就直接進入一般指令模式了(這是預設的模式,也簡稱為一般模式)。在這個模式中, 你可以使用『上下左右』按鍵來移動游標,你可以使用『刪除字元』或『刪除整列』來處理檔案內容, 也可以使用『複製、貼上』來處理你的文件資料。

  • 編輯模式 (insert mode)

在一般指令模式中可以進行刪除、複製、貼上等等的動作,但是卻無法編輯文件內容的! 要等到你按下『i, I, o, O, a, A, r, R』等任何一個字母之後才會進入編輯模式。注意了!通常在 Linux 中,按下這些按鍵時,在畫面的左下方會出現『 INSERT 或 REPLACE 』的字樣,此時才可以進行編輯。而如果要回到一般指令模式時, 則必須要按下『Esc』這個按鍵即可退出編輯模式。

  • 指令列命令模式 (command-line mode)

在一般模式當中,輸入『 : / ? 』三個中的任何一個按鈕,就可以將游標移動到最底下那一列。在這個模式當中, 可以提供你『搜尋資料』的動作,而讀取、存檔、大量取代字元、離開 vi 、顯示行號等等的動作則是在此模式中達成的!

簡單的說,我們可以將這三個模式想成底下的圖示來表示:

vi三種模式的相互關係
圖9.2.1、vi三種模式的相互關係

注意到上面的圖示,你會發現一般指令模式可與編輯模式及指令列模式切換, 但編輯模式與指令列模式之間不可互相切換喔!這非常重要啦!閒話不多說,我們底下以一個簡單的例子來進行說明吧!

Tips鳥哥的圖示 過去鳥哥的前一版本中,一般指令模式被稱為一般模式。但是英文版的 vi/vim 說明中,一般模式其實是『 command mode 』的意思!中文直譯會變成指令模式啊! 之所以稱為指令模式,主因是我們可以在一般模式底下按下很多特殊的指令功能!例如刪除、複製、區塊選擇等等!只是這個模式很容易跟指令列模式 (command-line) 混淆~ 所以鳥哥過去才稱為一般模式而已。不過真的很容易誤解啦!所以這一版開始,這一模式被鳥哥改為『一般指令模式』了!要尊重英文原文!

9.2.1 簡易執行範例

如果你想要使用 vi 來建立一個名為 welcome.txt 的檔案時,你可以這樣做:

  • 1. 使用『 vi filename 』進入一般指令模式
[dmtsai@study ~]$ /bin/vi welcome.txt
# 在 CentOS 7 當中,由於一般帳號預設 vi 已經被 vim 取代了,因此得要輸入絕對路徑來執行才行!

直接輸入『 vi 檔名』就能夠進入 vi 的一般指令模式了。不過請注意,由於一般帳號預設已經使用 vim 來取代,因此如上表所示, 如果使用一般帳號來測試,得要使用絕對路徑的方式來執行 /bin/vi 才好!另外,請注意,記得 vi 後面一定要加檔名,不管該檔名存在與否!

整個畫面主要分為兩部份,上半部與最底下一列兩者可以視為獨立的。如下圖 9.2.2 所示,圖中那個虛線是不存在的, 鳥哥用來說明而已啦!上半部顯示的是檔案的實際內容,最底下一列則是狀態顯示列(如下圖的[New File]資訊),或者是命令下達列喔!

用 vi 開啟一個新檔案
圖9.2.2、用 vi 開啟一個新檔案

如果你開啟的檔案是舊檔(已經存在的檔案),則可能會出現如下的資訊:

用 vi 開啟一個舊檔案
圖9.2.3、用 vi 開啟一個舊檔案

如上圖 9.2.3 所示,箭頭所指的那個『"/etc/man_db.conf" [readonly] 131L, 5171C』代表的是『現在開啟的檔名為 /etc/man_db.conf, 由於啟動者的身份緣故,目前檔案為唯讀狀態,且檔案內有 131 列 以及具有 5171 個字元』的意思!那一列的內容並不是在檔案內,而是 vi 顯示一些資訊的地方喔!此時是在一般指令模式的環境下啦。接下來開始來輸入吧!

  • 2. 按下 i 進入編輯模式,開始編輯文字

在一般指令模式之中,只要按下 i, o, a 等字元就可以進入編輯模式了!在編輯模式當中,你可以發現在左下角狀態列中會出現 –INSERT- 的字樣,那就是可以輸入任意字元的提示囉!這個時候,鍵盤上除了 [Esc] 這個按鍵之外,其他的按鍵都可以視作為一般的輸入按鈕了,所以你可以進行任何的編輯囉!

開始用 vi 來進行編輯
圖9.2.4、開始用 vi 來進行編輯
  • 3. 按下 [ESC] 按鈕回到一般指令模式

好了,假設我已經按照上面的樣式給他編輯完畢了,那麼應該要如何退出呢?是的!沒錯!就是給他按下 [Esc] 這個按鈕即可!馬上你就會發現畫面左下角的 – INSERT – 不見了!!

  • 4. 進入指令列模式,檔案儲存並離開 vi 環境

OK,我們要存檔了,存檔 (write) 並離開 (quit) 的指令很簡單,輸入『:wq』即可存檔離開! (注意了,按下 : 該游標就會移動到最底下一列去!) 這時你在提示字元後面輸入『 ls -l 』即可看到我們剛剛建立的 welcome.txt 檔案啦!整個圖示有點像底下這樣:

在指令列模式進行儲存及離開 vi 環境
圖9.2.5、在指令列模式進行儲存及離開 vi 環境

如此一來,你的檔案 welcome.txt 就已經建立起來囉!需要注意的是,如果你的檔案權限不對,例如為 -r--r--r-- 時,那麼可能會無法寫入,此時可以使用『強制寫入』的方式嗎?可以!使用『 :wq! 』 多加一個驚嘆號即可!不過,需要特別注意呦!那個是在『你的權限可以改變』的情況下才能成立的! 關於權限的概念,請自行回去翻一下第五章的內容吧!



9.2.2 按鍵說明

除了上面簡易範例的 i, [Esc], :wq 之外,其實 vi 還有非常多的按鍵可以使用喔!在介紹之前還是要再次強調, vi 的三種模式只有一般指令模式可以與編輯、指令列模式切換,編輯模式與指令列模式之間並不能切換的! 這點在圖9.2.1裡面有介紹到,注意去看看喔!底下就來談談 vi 軟體中會用到的按鍵功能吧!

  • 第一部份:一般指令模式可用的按鈕說明,游標移動、複製貼上、搜尋取代等
移動游標的方法
h 或 向左方向鍵(←) 游標向左移動一個字元
j 或 向下方向鍵(↓) 游標向下移動一個字元
k 或 向上方向鍵(↑) 游標向上移動一個字元
l 或 向右方向鍵(→) 游標向右移動一個字元
如果你將右手放在鍵盤上的話,你會發現 hjkl 是排列在一起的,因此可以使用這四個按鈕來移動游標。 如果想要進行多次移動的話,例如向下移動 30 列,可以使用 "30j" 或 "30↓" 的組合按鍵, 亦即加上想要進行的次數(數字)後,按下動作即可!
[Ctrl] + [f] 螢幕『向下』移動一頁,相當於 [Page Down]按鍵 (常用)
[Ctrl] + [b] 螢幕『向上』移動一頁,相當於 [Page Up] 按鍵 (常用)
[Ctrl] + [d] 螢幕『向下』移動半頁
[Ctrl] + [u] 螢幕『向上』移動半頁
+ 游標移動到非空白字元的下一列
- 游標移動到非空白字元的上一列
n<space> 那個 n 表示『數字』,例如 20 。按下數字後再按空白鍵,游標會向右移動這一列的 n 個字元。例如 20<space> 則游標會向後面移動 20 個字元距離。
0 或功能鍵[Home] 這是數字『 0 』:移動到這一列的最前面字元處 (常用)
$ 或功能鍵[End] 移動到這一列的最後面字元處(常用)
H 游標移動到這個螢幕的最上方那一列的第一個字元
M 游標移動到這個螢幕的中央那一列的第一個字元
L 游標移動到這個螢幕的最下方那一列的第一個字元
G 移動到這個檔案的最後一列(常用)
nG n 為數字。移動到這個檔案的第 n 列。例如 20G 則會移動到這個檔案的第 20 列(可配合 :set nu)
gg 移動到這個檔案的第一列,相當於 1G 啊! (常用)
n<Enter> n 為數字。游標向下移動 n 列(常用)
搜尋與取代
/word 向游標之下尋找一個名稱為 word 的字串。例如要在檔案內搜尋 vbird 這個字串,就輸入 /vbird 即可! (常用)
?word 向游標之上尋找一個字串名稱為 word 的字串。
n 這個 n 是英文按鍵。代表『重複前一個搜尋的動作』。舉例來說, 如果剛剛我們執行 /vbird 去向下搜尋 vbird 這個字串,則按下 n 後,會向下繼續搜尋下一個名稱為 vbird 的字串。如果是執行 ?vbird 的話,那麼按下 n 則會向上繼續搜尋名稱為 vbird 的字串!
N 這個 N 是英文按鍵。與 n 剛好相反,為『反向』進行前一個搜尋動作。 例如 /vbird 後,按下 N 則表示『向上』搜尋 vbird 。
使用 /word 配合 n 及 N 是非常有幫助的!可以讓你重複的找到一些你搜尋的關鍵字!
:n1,n2s/word1/word2/g n1 與 n2 為數字。在第 n1 與 n2 列之間尋找 word1 這個字串,並將該字串取代為 word2 !舉例來說,在 100 到 200 列之間搜尋 vbird 並取代為 VBIRD 則:
『:100,200s/vbird/VBIRD/g』。(常用)
:1,$s/word1/word2/g 從第一列到最後一列尋找 word1 字串,並將該字串取代為 word2 !(常用)
:1,$s/word1/word2/gc 從第一列到最後一列尋找 word1 字串,並將該字串取代為 word2 !且在取代前顯示提示字元給使用者確認 (confirm) 是否需要取代!(常用)
刪除、複製與貼上
x, X 在一列字當中,x 為向後刪除一個字元 (相當於 [del] 按鍵), X 為向前刪除一個字元(相當於 [backspace] 亦即是倒退鍵) (常用)
nx n 為數字,連續向後刪除 n 個字元。舉例來說,我要連續刪除 10 個字元, 『10x』。
dd 刪除游標所在的那一整列(常用)
ndd n 為數字。刪除游標所在的向下 n 列,例如 20dd 則是刪除 20 列 (常用)
d1G 刪除游標所在到第一列的所有資料
dG 刪除游標所在到最後一列的所有資料
d$ 刪除游標所在處,到該列的最後一個字元
d0 那個是數字的 0 ,刪除游標所在處,到該列的最前面一個字元
yy 複製游標所在的那一列(常用)
nyy n 為數字。複製游標所在的向下 n 列,例如 20yy 則是複製 20 列(常用)
y1G 複製游標所在列到第一列的所有資料
yG 複製游標所在列到最後一列的所有資料
y0 複製游標所在的那個字元到該列行首的所有資料
y$ 複製游標所在的那個字元到該列行尾的所有資料
p, P p 為將已複製的資料在游標下一列貼上,P 則為貼在游標上一列! 舉例來說,我目前游標在第 20 列,且已經複製了 10 列資料。則按下 p 後, 那 10 列資料會貼在原本的 20 列之後,亦即由 21 列開始貼。但如果是按下 P 呢? 那麼原本的第 20 列會被推到變成 30 列。 (常用)
J 將游標所在列與下一列的資料結合成同一列
c 重複刪除多個資料,例如向下刪除 10 列,[ 10cj ]
u 復原前一個動作。(常用)
[Ctrl]+r 重做上一個動作。(常用)
這個 u 與 [Ctrl]+r 是很常用的指令!一個是復原,另一個則是重做一次~ 利用這兩個功能按鍵,你的編輯,嘿嘿!很快樂的啦!
. 不要懷疑!這就是小數點!意思是重複前一個動作的意思。 如果你想要重複刪除、重複貼上等等動作,按下小數點『.』就好了! (常用)
  • 第二部份:一般指令模式切換到編輯模式的可用的按鈕說明
進入插入或取代的編輯模式
i, I 進入插入模式(Insert mode):
i 為『從目前游標所在處插入』, I 為『在目前所在列的第一個非空白字元處開始插入』。 (常用)
a, A 進入插入模式(Insert mode):
a 為『從目前游標所在的下一個字元處開始插入』, A 為『從游標所在列的最後一個字元處開始插入』。(常用)
o, O 進入插入模式(Insert mode):
這是英文字母 o 的大小寫。o 為『在目前游標所在的下一列處插入新的一列』; O 為在目前游標所在處的上一列插入新的一列!(常用)
r, R 進入取代模式(Replace mode):
r 只會取代游標所在的那一個字元一次;R會一直取代游標所在的文字,直到按下 ESC 為止;(常用)
上面這些按鍵中,在 vi 畫面的左下角處會出現『--INSERT--』或『--REPLACE--』的字樣。 由名稱就知道該動作了吧!!特別注意的是,我們上面也提過了,你想要在檔案裡面輸入字元時, 一定要在左下角處看到 INSERT 或 REPLACE 才能輸入喔!
[Esc] 退出編輯模式,回到一般指令模式中(常用)
  • 第三部份:一般指令模式切換到指令列模式的可用按鈕說明
指令列模式的儲存、離開等指令
:w 將編輯的資料寫入硬碟檔案中(常用)
:w! 若檔案屬性為『唯讀』時,強制寫入該檔案。不過,到底能不能寫入, 還是跟你對該檔案的檔案權限有關啊!
:q 離開 vi (常用)
:q! 若曾修改過檔案,又不想儲存,使用 ! 為強制離開不儲存檔案。
注意一下啊,那個驚嘆號 (!) 在 vi 當中,常常具有『強制』的意思~
:wq 儲存後離開,若為 :wq! 則為強制儲存後離開 (常用)
ZZ 這是大寫的 Z 喔!若檔案沒有更動,則不儲存離開,若檔案已經被更動過,則儲存後離開!
:w [filename] 將編輯的資料儲存成另一個檔案(類似另存新檔)
:r [filename] 在編輯的資料中,讀入另一個檔案的資料。亦即將 『filename』 這個檔案內容加到游標所在列後面
:n1,n2 w [filename] 將 n1 到 n2 的內容儲存成 filename 這個檔案。
:! command 暫時離開 vi 到指令列模式下執行 command 的顯示結果!例如
『:! ls /home』即可在 vi 當中察看 /home 底下以 ls 輸出的檔案資訊!
vim 環境的變更
:set nu 顯示行號,設定之後,會在每一列的字首顯示該列的行號
:set nonu 與 set nu 相反,為取消行號!

特別注意,在 vi 中,『數字』是很有意義的!數字通常代表重複做幾次的意思! 也有可能是代表去到第幾個什麼什麼的意思。舉例來說,要刪除 50 列,則是用 『50dd』 對吧! 數字加在動作之前~那我要向下移動 20 列呢?那就是『20j』或者是『20↓』即可。

OK!會這些指令就已經很厲害了,因為常用到的指令也只有不到一半!通常 vi 的指令除了上面鳥哥註明的常用的幾個外,其他是不用背的,你可以做一張簡單的指令表在你的螢幕牆上, 一有疑問可以馬上的查詢呦!這也是當初鳥哥使用 vim 的方法啦!



9.2.3 一個案例練習

來來來!趕緊測試一下你是否已經熟悉 vi 這個指令呢?請依照底下的需求進行指令動作。 (底下的操作為使用 CentOS 7.1 中的 man_db.conf 來做練習的,該檔案你可以在這裡下載: http://linux.vbird.org/linux_basic/0310vi/man_db.conf。) 看看你的顯示結果與鳥哥的結果是否相同啊?

  1. 請在 /tmp 這個目錄下建立一個名為 vitest 的目錄;
  2. 進入 vitest 這個目錄當中;
  3. 將 /etc/man_db.conf 複製到本目錄底下(或由上述的連結下載 man_db.conf 檔案);
  4. 使用 vi 開啟本目錄下的 man_db.conf 這個檔案;
  5. 在 vi 中設定一下行號;
  6. 移動到第 43 列,向右移動 59 個字元,請問你看到的小括號內是哪個文字?
  7. 移動到第一列,並且向下搜尋一下『 gzip 』這個字串,請問他在第幾列?
  8. 接著下來,我要將 29 到 41 列之間的『小寫 man 字串』改為『大寫 MAN 字串』,並且一個一個挑選是否需要修改,如何下達指令?如果在挑選過程中一直按『y』, 結果會在最後一列出現改變了幾個 man 呢?
  9. 修改完之後,突然反悔了,要全部復原,有哪些方法?
  10. 我要複製 66 到 71 這 6 列的內容(含有MANDB_MAP),並且貼到最後一列之後;
  11. 113 到 128 列之間的開頭為 # 符號的註解資料我不要了,要如何刪除?
  12. 將這個檔案另存成一個 man.test.config 的檔名;
  13. 去到第 25 列,並且刪除 15 個字元,結果出現的第一個單字是什麼?
  14. 在第一列新增一列,該列內容輸入『I am a student...』;
  15. 儲存後離開吧!

整個步驟可以如下顯示:

  1. 『mkdir /tmp/vitest』
  2. 『cd /tmp/vitest』
  3. 『cp /etc/man_db.conf .』
  4. 『/bin/vi man_db.conf』
  5. 『:set nu』然後你會在畫面中看到左側出現數字即為行號。
  6. 先按下『43G』再按下『59→』會看到『 as 』這個單字在小括號內;
  7. 先執行『1G』或『gg』後,直接輸入『/gzip』,則會去到第 93 列才對!
  8. 直接下達『 :29,41s/man/MAN/gc 』即可!若一直按『y』最終會出現『在 13 列內置換 13 個字串』的說明。
  9. (1)簡單的方法可以一直按『 u 』回復到原始狀態,(2)使用不儲存離開『 :q! 』之後,再重新讀取一次該檔案;
  10. 『66G』 然後再『 6yy 』之後最後一列會出現『複製6列』之類的說明字樣。 按下『 G 』到最後一列,再給他『 p 』貼上6列!
  11. 因為 113~128 共 16 列,因此『 113G 』→『 16dd 』就能刪除 16 列,此時你會發現游標所在 113 列的地方變成 『 # Flags. 』 開頭囉
  12. 『 :w man.test.config 』,你會發現最後一列出現 "man.test.config" [New].. 的字樣。
  13. 『25G』 之後,再給他『 15x 』即可刪除 15 個字元,出現『 tree 』的字樣;
  14. 先『 1G 』去到第一列,然後按下大寫的『 O 』便新增一列且在插入模式;開始輸入『I am a student...』後, 按下[Esc]回到一般指令模式等待後續工作;
  15. 『:wq』

如果你的結果都可以查的到,那麼 vi 的使用上面應該沒有太大的問題啦!剩下的問題會是在…打字練習…。



9.2.4 vim 的暫存檔、救援回復與開啟時的警告訊息

在目前主要的文書編輯軟體都會有『回復』的功能,亦即當你的系統因為某些原因而導致類似當機的情況時, 還可以透過某些特別的機制來讓你將之前未儲存的資料『救』回來!這就是鳥哥這裡所謂的『回復』功能啦! 那麼 vim 有沒有回復功能呢?有的! vim 就是透過『暫存檔』來救援的啦!

當我們在使用 vim 編輯時, vim 會在與被編輯的檔案的目錄下,再建立一個名為 .filename.swp 的檔案。 比如說我們在上一個小節談到的編輯 /tmp/vitest/man_db.conf 這個檔案時, vim 會主動的建立 /tmp/vitest/.man_db.conf.swp 的暫存檔,你對 man_db.conf 做的動作就會被記錄到這個 .man_db.conf.swp 當中喔!如果你的系統因為某些原因斷線了, 導致你編輯的檔案還沒有儲存,這個時候 .man_db.conf.swp 就能夠發揮救援的功能了!我們來測試一下吧! 底下的練習有些部分的指令我們尚未談到,沒關係,你先照著做,後續再回來瞭解囉!

[dmtsai@study ~]$ cd /tmp/vitest
[dmtsai@study vitest]$ vim man_db.conf
# 此時會進入到 vim 的畫面,請在 vim 的一般指令模式下按下『 [ctrl]-z 』的組合鍵

[1]+  Stopped             vim man_db.conf  <==按下 [ctrl]-z 會告訴你這個訊息

當我們在 vim 的一般指令模式下按下 [ctrl]-z 的組合按鍵時,你的 vim 會被丟到背景去執行! 這部份的功能我們會在第十六章的程序管理當中談到, 你這裡先知道一下即可。回到命令提示字元後,接下來我們來模擬將 vim 的工作不正常的中斷吧!

[dmtsai@study vitest]$ ls -al
drwxrwxr-x.  2 dmtsai dmtsai    69 Jul  6 23:54 .
drwxrwxrwt. 17 root   root    4096 Jul  6 23:53 ..
-rw-r--r--.  1 dmtsai dmtsai  4850 Jul  6 23:47 man_db.conf
-rw-r--r--.  1 dmtsai dmtsai 16384 Jul  6 23:54 .man_db.conf.swp  <==就是他,暫存檔
-rw-rw-r--.  1 dmtsai dmtsai  5442 Jul  6 23:35 man.test.config

[dmtsai@study vitest]$ kill -9 %1 <==這裡模擬斷線停止 vim 工作
[dmtsai@study vitest]$ ls -al .man_db.conf.swp
-rw-r--r--. 1 dmtsai dmtsai 16384 Jul  6 23:54 .man_db.conf.swp  <==暫存檔還是會存在!

那個 kill 可以模擬將系統的 vim 工作刪除的情況,你可以假裝當機了啦! 由於 vim 的工作被不正常的中斷,導致暫存檔無法藉由正常流程來結束, 所以暫存檔就不會消失,而繼續保留下來。此時如果你繼續編輯那個 man_db.conf ,會出現什麼情況呢? 會出現如下所示的狀態喔:

[dmtsai@study vitest]$ vim man_db.conf

E325: ATTENTION  <==錯誤代碼
Found a swap file by the name ".man_db.conf.swp"  <==底下數列說明有暫存檔的存在
          owned by: dmtsai   dated: Mon Jul  6 23:54:16 2015
         file name: /tmp/vitest/man_db.conf  <==這個暫存檔屬於哪個實際的檔案?
          modified: no
         user name: dmtsai   host name: study.centos.vbird
        process ID: 31851
While opening file "man_db.conf"
             dated: Mon Jul  6 23:47:21 2015

底下說明可能發生這個錯誤的兩個主要原因與解決方案!
(1) Another program may be editing the same file.  If this is the case,
    be careful not to end up with two different instances of the same
    file when making changes.  Quit, or continue with caution.
(2) An edit session for this file crashed.
    If this is the case, use ":recover" or "vim -r man_db.conf"
    to recover the changes (see ":help recovery").
    If you did this already, delete the swap file ".man_db.conf.swp"
    to avoid this message.

Swap file ".man_db.conf.swp" already exists! 底下說明你可進行的動作
[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:  

由於暫存檔存在的關係,因此 vim 會主動的判斷你的這個檔案可能有些問題,在上面的圖示中 vim 提示兩點主要的問題與解決方案,分別是這樣的:

  • 問題一:可能有其他人或程式同時在編輯這個檔案:

    由於 Linux 是多人多工的環境,因此很可能有很多人同時在編輯同一個檔案。如果在多人共同編輯的情況下, 萬一大家同時儲存,那麼這個檔案的內容將會變的亂七八糟!為了避免這個問題,因此 vim 會出現這個警告視窗! 解決的方法則是:

    • 找到另外那個程式或人員,請他將該 vim 的工作結束,然後你再繼續處理。

    • 如果你只是要看該檔案的內容並不會有任何修改編輯的行為,那麼可以選擇開啟成為唯讀(O)檔案, 亦即上述畫面反白部分輸入英文『 o 』即可,其實就是 [O]pen Read-Only 的選項啦!

  • 問題二:在前一個 vim 的環境中,可能因為某些不知名原因導致 vim 中斷 (crashed):

    這就是常見的不正常結束 vim 產生的後果。解決方案依據不同的情況而不同喔!常見的處理方法為:

    • 如果你之前的 vim 處理動作尚未儲存,此時你應該要按下『R』,亦即使用 (R)ecover 的項目, 此時 vim 會載入 .man_db.conf.swp 的內容,讓你自己來決定要不要儲存!這樣就能夠救回來你之前未儲存的工作。 不過那個 .man_db.conf.swp 並不會在你結束 vim 後自動刪除,所以你離開 vim 後還得要自行刪除 .man_db.conf.swp 才能避免每次打開這個檔案都會出現這樣的警告

    • 如果你確定這個暫存檔是沒有用的,那麼你可以直接按下『D』刪除掉這個暫存檔,亦即 (D)elete it 這個項目即可。 此時 vim 會載入 man_db.conf ,並且將舊的 .man_db.conf.swp 刪除後,建立這次會使用的新的 .man_db.conf.swp 喔!

至於這個發現暫存檔警告訊息的畫面中,有出現六個可用按鈕,各按鈕的說明如下:

  • [O]pen Read-Only:打開此檔案成為唯讀檔, 可以用在你只是想要查閱該檔案內容並不想要進行編輯行為時。一般來說,在上課時,如果你是登入到同學的電腦去看他的設定檔, 結果發現其實同學他自己也在編輯時,可以使用這個模式;

  • (E)dit anyway:還是用正常的方式打開你要編輯的那個檔案, 並不會載入暫存檔的內容。不過很容易出現兩個使用者互相改變對方的檔案等問題!不好不好!

  • (R)ecover:就是載入暫存檔的內容,用在你要救回之前未儲存的工作。 不過當你救回來並且儲存離開 vim 後,還是要手動自行刪除那個暫存檔喔!

  • (D)elete it:你確定那個暫存檔是無用的!那麼開啟檔案前會先將這個暫存檔刪除! 這個動作其實是比較常做的!因為你可能不確定這個暫存檔是怎麼來的,所以就刪除掉他吧!哈哈!

  • (Q)uit:按下 q 就離開 vim ,不會進行任何動作回到命令提示字元。

  • (A)bort:忽略這個編輯行為,感覺上與 quit 非常類似! 也會送你回到命令提示字元就是囉!

9.3 vim 的額外功能

其實,目前大部分的 distributions 都以 vim 取代 vi 的功能了!如果你使用 vi 後,卻看到畫面的右下角有顯示目前游標所在的行列號碼,那麼你的 vi 已經被 vim 所取代囉~為什麼要用 vim 呢?因為 vim 具有顏色顯示的功能,並且還支援許多的程式語法 (syntax), 因此,當你使用 vim 編輯程式時 (不論是 C 語言,還是 shell script ),我們的 vim 將可幫你直接進行『程式除錯 (debug)』的功能!真的很不賴吧!^_^

如果你在文字模式下,輸入 alias 時,出現這樣的畫面:

[dmtsai@study ~]$ alias
....其他省略....
alias vi='vim'  <==重點在這列啊!

這表示當你使用 vi 這個指令時,其實就是執行 vim 啦!如果你沒有這一列,那麼你就必須要使用 vim filename 來啟動 vim 囉!基本上, vim 的一般用法與 vi 完全一模一樣~沒有不同啦!那麼我們就來看看 vim 的畫面是怎樣囉!假設我想要編輯 /etc/services ,則輸入『vim /etc/services』看看吧:

使用 vim 編輯系統設定檔的示範
圖9.3.1、使用 vim 編輯系統設定檔的示範

上面是 vim 的畫面示意圖,在這個畫面中有幾點特色要說明喔:

  1. 由於 /etc/services 是系統規劃的設定檔,因此 vim 會進行語法檢驗,所以你會看到畫面中內部主要為深藍色, 且深藍色那一列是以註解符號 (#) 為開頭;
  2. 畫面中的最底下一列,在左邊顯示該檔案的屬性,包括唯讀檔、內容共有 11176 列與 670293 個字元;
  3. 最底下一列的右邊出現的 1,1 表示游標所在為第一列, 第一個字元位置之意(請看上圖中的游標所在);

所以,如果你向下移動到其他位置時,出現的非註解的資料就會有點像這樣:

使用 vim 編輯系統設定檔的示範
圖9.3.2、使用 vim 編輯系統設定檔的示範

看到了喔!除了註解之外,其他的列就會有特別的顏色顯示呢!可以避免你打錯字啊!而且, 最右下角的 1% 代表目前這個畫面佔整體檔案的 1% 之意!這樣瞭乎?

9.3.1 區塊選擇(Visual Block)

剛剛我們提到的簡單的 vi 操作過程中,幾乎提到的都是以列為單位的操作。那麼如果我想要搞定的是一個區塊範圍呢? 舉例來說,像底下這種格式的檔案:

192.168.1.1    host1.class.net
192.168.1.2    host2.class.net
192.168.1.3    host3.class.net
192.168.1.4    host4.class.net
.....中間省略......

這個檔案我將他放置到 http://linux.vbird.org/linux_basic/0310vi/hosts ,你可以自行下載來看一看這個檔案啊!現在我們來玩一玩這個檔案吧!假設我想要將 host1, host2... 等等複製起來, 並且加到每一列的後面,亦即每一列的結果要是『 192.168.1.2 host2.class.net host2 』這樣的情況時, 在傳統或現代的視窗型編輯器似乎不容易達到這個需求,但是咱們的 vim 是辦的到的喔!那就使用區塊選擇 (Visual Block) 吧!當我們按下 v 或者 V 或者 [Ctrl]+v 時, 這個時候游標移動過的地方就會開始反白,這三個按鍵的意義分別是:

區塊選擇的按鍵意義
v字元選擇,會將游標經過的地方反白選擇!
V列選擇,會將游標經過的列反白選擇!
[Ctrl]+v區塊選擇,可以用長方形的方式選擇資料
y將反白的地方複製起來
d將反白的地方刪除掉
p將剛剛複製的區塊,在游標所在處貼上!

來實際進行我們需要的動作吧!就是將 host 再加到每一列的最後面,你可以這樣做:

  1. 使用 vim hosts 來開啟該檔案,記得該檔案請由上述的連結下載先!
  2. 將游標移動到第一列的 host 那個 h 上頭,然後按下 [ctrl]-v ,左下角出現區塊示意字樣:

    vim 的區塊選擇、複製、貼上等操作功能
    圖9.3.3、vim 的區塊選擇、複製、貼上等功能操作
  3. 將游標移動到最底部,此時游標移動過的區域會反白!如下圖所示:

    vim 的區塊選擇、複製、貼上等操作功能
    圖9.3.4、vim 的區塊選擇、複製、貼上等功能操作
  4. 此時你可以按下『 y 』來進行複製,當你按下 y 之後,反白的區塊就會消失不見囉!
  5. 最後,將游標移動到第一列的最右邊,並且再用編輯模式向右按兩個空白鍵,回到一般指令模式後, 再按下『 p 』後,你會發現很有趣!如下圖所示:

    vim 的區塊選擇、複製、貼上等操作功能
    圖9.3.5、vim 的區塊選擇、複製、貼上等功能操作

透過上述的功能,你可以複製一個區塊,並且是貼在某個『區塊的範圍』內,而不是以列為單位來處理你的整份文件喔! 鳥哥個人是覺得這玩意兒非常的有幫助啦!至少在進行排列整齊的文字檔案中複製/刪除區塊時,會是一個非常棒的功能!



9.3.2 多檔案編輯

假設一個例子,你想要將剛剛我們的 hosts 內的 IP 複製到你的 /etc/hosts 這個檔案去, 那麼該如何編輯?我們知道在 vi 內可以使用 :r filename 來讀入某個檔案的內容, 不過,這樣畢竟是將整個檔案讀入啊!如果我只是想要部分內容呢?呵呵!這個時候多檔案同時編輯就很有用了。 我們可以使用 vim 後面同時接好幾個檔案來同時開啟喔!相關的按鍵有:

多檔案編輯的按鍵
:n編輯下一個檔案
:N編輯上一個檔案
:files列出目前這個 vim 的開啟的所有檔案

在過去,鳥哥想要將 A 檔案內的十條消息『移動』到 B 檔案去,通常要開兩個 vim 視窗來複製, 偏偏每個 vim 都是獨立的,因此並沒有辦法在 A 檔案下達『 nyy 』再跑到 B 檔案去『 p 』啦! 在這種情況下最常用的方法就是透過滑鼠圈選, 複製後貼上。不過這樣一來還是有問題,因為鳥哥超級喜歡使用 [Tab] 按鍵進行編排對齊動作, 透過滑鼠卻會將 [Tab] 轉成空白鍵,這樣內容就不一樣了!此時這個多檔案編輯就派上用場了!

現在你可以做一下練習看看說!假設你要將剛剛鳥哥提供的 hosts 內的前四列 IP 資料複製到你的 /etc/hosts 檔案內,那可以怎麼進行呢?可以這樣啊:

  1. 透過『 vim hosts /etc/hosts 』指令來使用一個 vim 開啟兩個檔案;
  2. 在 vim 中先使用『 :files 』察看一下編輯的檔案資料有啥?結果如下所示。 至於下圖的最後一列顯示的是『按下任意鍵』就會回到 vim 的一般指令模式中!

    vim 的多檔案編輯中,查看同時編輯的檔案資料
    圖9.3.6、vim 的多檔案編輯中,查看同時編輯的檔案資料
  3. 在第一列輸入『 4yy 』複製四列;
  4. 在 vim 的環境下輸入『 :n 』會來到第二個編輯的檔案,亦即 /etc/hosts 內;
  5. 在 /etc/hosts 下按『 G 』到最後一列,再輸入『 p 』貼上;
  6. 按下多次的『 u 』來還原原本的檔案資料;
  7. 最終按下『 :q 』來離開 vim 的多檔案編輯吧!

看到了吧?利用多檔案編輯的功能,可以讓你很快速的就將需要的資料複製到正確的檔案內。 當然囉,這個功能也可以利用視窗介面來達到,那就是底下要提到的多視窗功能。



9.3.3 多視窗功能

在開始這個小節前,先來想像兩個情況:

  • 當我有一個檔案非常的大,我查閱到後面的資料時,想要『對照』前面的資料, 是否需要使用 [ctrl]+f 與 [ctrl]+b (或 pageup, pagedown 功能鍵) 來跑前跑後查閱?

  • 我有兩個需要對照著看的檔案,不想使用前一小節提到的多檔案編輯功能;

在一般視窗介面下的編輯軟體大多有『分割視窗』或者是『凍結視窗』的功能來將一個檔案分割成多個視窗的展現, 那麼 vim 能不能達到這個功能啊?可以啊!但是如何分割視窗並放入檔案呢? 很簡單啊!在指令列模式輸入『:sp {filename}』即可!那個 filename 可有可無, 如果想要在新視窗啟動另一個檔案,就加入檔名,否則僅輸入 :sp 時, 出現的則是同一個檔案在兩個視窗間

讓我們來測試一下,你先使用『 vim /etc/man_db.conf 』打開這個檔案,然後『 1G 』去到第一列,之後輸入『 :sp 』 再次的打開這個檔案一次,然後再輸入『 G 』,結果會變成底下這樣喔:

vim 的視窗分割示意圖
圖9.3.7、vim 的視窗分割示意圖

萬一你再輸入『 :sp /etc/hosts 』時,就會變成下圖這樣喔:

vim 的視窗分割示意圖
圖9.3.8、vim 的視窗分割示意圖

怎樣?帥吧!兩個檔案同時在一個螢幕上面顯示,你還可以利用『[ctrl]+w+↑』及『[ctrl]+w+↓』 在兩個視窗之間移動呢!這樣的話,複製啊、查閱啊等等的,就變的很簡單囉~ 分割視窗的相關指令功能有很多,不過你只要記得這幾個就好了:

多視窗情況下的按鍵功能
:sp [filename]開啟一個新視窗,如果有加 filename, 表示在新視窗開啟一個新檔案,否則表示兩個視窗為同一個檔案內容(同步顯示)。
[ctrl]+w+ j
[ctrl]+w+↓
按鍵的按法是:先按下 [ctrl] 不放, 再按下 w 後放開所有的按鍵,然後再按下 j (或向下方向鍵),則游標可移動到下方的視窗。
[ctrl]+w+ k
[ctrl]+w+↑
同上,不過游標移動到上面的視窗。
[ctrl]+w+ q其實就是 :q 結束離開啦! 舉例來說,如果我想要結束下方的視窗,那麼利用 [ctrl]+w+↓ 移動到下方視窗後,按下 :q 即可離開, 也可以按下 [ctrl]+w+q 啊!

鳥哥第一次玩 vim 的分割視窗時,真是很高興啊!竟然有這種功能!太棒了! ^_^



9.3.4 vim 的挑字補全功能

我們知道 bash 的環境底下可以按下 [tab] 按鈕來達成指令/參數/檔名的補全功能,而我們也知道很多的程式編輯器,例如鳥哥用來在 windows 系統上面教網頁設計、java script 等很好用的 notepad++ (https://notepad-plus-plus.org/) 這種類的程式編輯器,都會有 (1)可以進行語法檢驗及 (2)可以根據副檔名來挑字的功能!這兩個功能對於程式設計者來說, 是很有幫助的!畢竟偶爾某些特定的關鍵字老是背不起來...

在語法檢驗方面,vim 已經使用顏色來達成了!這部份不用傷腦筋的!比較傷腦筋的應該是在挑字補全上面!就是上面談到的可以根據語法來挑選可能的關鍵字, 包括程式語言的語法以及特定的語法關鍵字等等。既然 notepad ++ 都有支援了,沒道理 vim 不支援吧?呵呵!沒錯! 是有支援的~只是你可能要多背兩個組合按鈕就是了!

鳥哥建議可以記憶的主要 vim 補齊功能,大致有底下幾個:

組合按鈕補齊的內容
[ctrl]+x -> [ctrl]+n透過目前正在編輯的這個『檔案的內容文字』作為關鍵字,予以補齊
[ctrl]+x -> [ctrl]+f以當前目錄內的『檔名』作為關鍵字,予以補齊
[ctrl]+x -> [ctrl]+o以副檔名作為語法補充,以 vim 內建的關鍵字,予以補齊

在鳥哥的認知中,比較有用的是第1, 3 這兩個組合鍵,第一個組合按鍵中,你可能會在同一個檔案裡面重複出現許多相同的關鍵字, 那麼就能夠透過這個補全的功能來處理。如果你是想要使用 vim 內建的語法檢驗功能來處理取得關鍵字的補全,那麼第三個項目就很有用了。 不過要注意,如果你想要使用第三個功能,就得要注意你編輯的檔案的副檔名。我們底下來做個簡單測試好了。

假設你想要編寫網頁,正要使用到 CSS 的美化功能時,突然想到有個背景的東西要處理,但是突然忘記掉背景的 CSS 關鍵語法,那可以使用如下的模樣來處置! 請注意,一定要使用 .html 或 .php 的副檔名,否則 vim 不會呼叫正確的語法檢驗功能喔!因此底下我們建立的檔名為 html.html 囉!

vim 的挑字補全功能
圖9.3.9、vim 的挑字補全功能

由於網頁通常會支援 CSS 的語法,而 CSS 的美化語法使用的是 style 這個關鍵字,這個關鍵字後面接的就是 CSS 的元素與元素值。 若想要取得可能的元素有哪些,例如背景 (background) 的語法中,想要了解有哪些跟它有關的內建元素,如上圖, 直接輸入 b 然後按下 [ctrl]+x 再按下 [ctrl]+o 就會出現如上的相關字詞可以選擇,此時你就能夠使用上下按鈕來挑選所需要的關鍵元素! 這樣使用上當然方便很多啊!只是要注意,一定要使用正確的副檔名,否則會無法出現任何關鍵字詞喔!



9.3.5 vim 環境設定與記錄: ~/.vimrc, ~/.viminfo

有沒有發現,如果我們以 vim 軟體來搜尋一個檔案內部的某個字串時,這個字串會被反白, 而下次我們再次以 vim 編輯這個檔案時,該搜尋的字串反白情況還是存在呢!甚至於在編輯其他檔案時, 如果其他檔案內也存在這個字串,哇!竟然還是主動反白耶!真神奇! 另外,當我們重複編輯同一個檔案時,當第二次進入該檔案時, 游標竟然就在上次離開的那一列上頭呢!真是好方便啊~但是,怎麼會這樣呢?

這是因為我們的 vim 會主動的將你曾經做過的行為登錄下來,好讓你下次可以輕鬆的作業啊! 那個記錄動作的檔案就是: ~/.viminfo !如果你曾經使用過 vim, 那你的家目錄應該會存在這個檔案才對。這個檔案是自動產生的, 你不必自行建立。而你在 vim 裡頭所做過的動作,就可以在這個檔案內部查詢到囉~ ^_^

此外,每個 distributions 對 vim 的預設環境都不太相同,舉例來說,某些版本在搜尋到關鍵字時並不會高亮度反白, 有些版本則會主動的幫你進行縮排的行為。但這些其實都可以自行設定的,那就是 vim 的環境設定囉~ vim 的環境設定參數有很多,如果你想要知道目前的設定值,可以在一般指令模式時輸入『 :set all 』 來查閱,不過.....設定項目實在太多了~所以,鳥哥在這裡僅列出一些平時比較常用的一些簡單的設定值, 提供給你參考啊。

Tips鳥哥的圖示 所謂的縮排,就是當你按下 Enter 編輯新的一列時,游標不會在行首,而是在與上一列的第一個非空白字元處對齊!

vim 的環境設定參數
:set nu
:set nonu
就是設定與取消行號啊!
:set hlsearch
:set nohlsearch
hlsearch 就是 high light search(高亮度搜尋)。 這個就是設定是否將搜尋的字串反白的設定值。預設值是 hlsearch
:set autoindent
:set noautoindent
是否自動縮排?autoindent 就是自動縮排。
:set backup是否自動儲存備份檔?一般是 nobackup 的, 如果設定 backup 的話,那麼當你更動任何一個檔案時,則原始檔案會被另存成一個檔名為 filename~ 的檔案。 舉例來說,我們編輯 hosts ,設定 :set backup ,那麼當更動 hosts 時,在同目錄下,就會產生 hosts~ 檔名的檔案,記錄原始的 hosts 檔案內容
:set ruler還記得我們提到的右下角的一些狀態列說明嗎? 這個 ruler 就是在顯示或不顯示該設定值的啦!
:set showmode這個則是,是否要顯示 --INSERT-- 之類的字眼在左下角的狀態列。
:set backspace=(012)一般來說, 如果我們按下 i 進入編輯模式後,可以利用倒退鍵 (backspace) 來刪除任意字元的。 但是,某些 distribution 則不許如此。此時,我們就可以透過 backspace 來設定囉~ 當 backspace 為 2 時,就是可以刪除任意值;0 或 1 時,僅可刪除剛剛輸入的字元, 而無法刪除原本就已經存在的文字了!
:set all顯示目前所有的環境參數設定值。
:set顯示與系統預設值不同的設定參數, 一般來說就是你有自行變動過的設定參數啦!
:syntax on
:syntax off
是否依據程式相關語法顯示不同顏色? 舉例來說,在編輯一個純文字檔時,如果開頭是以 # 開始,那麼該列就會變成藍色。 如果你懂得寫程式,那麼這個 :syntax on 還會主動的幫你除錯呢!但是, 如果你僅是編寫純文字檔案,要避免顏色對你的螢幕產生的干擾,則可以取消這個設定 。
:set bg=dark
:set bg=light
可用以顯示不同的顏色色調,預設是『 light 』。如果你常常發現註解的字體深藍色實在很不容易看, 那麼這裡可以設定為 dark 喔!試看看,會有不同的樣式呢!

總之,這些設定值很有用處的啦!但是......我是否每次使用 vim 都要重新設定一次各個參數值? 這不太合理吧?沒錯啊!所以,我們可以透過設定檔來直接規定我們習慣的 vim 操作環境呢! 整體 vim 的設定值一般是放置在 /etc/vimrc 這個檔案,不過,不建議你修改他! 你可以修改 ~/.vimrc 這個檔案 (預設不存在,請你自行手動建立!),將你所希望的設定值寫入! 舉例來說,可以是這樣的一個檔案:

[dmtsai@study ~]$ vim ~/.vimrc
"這個檔案的雙引號 (") 是註解
set hlsearch            "高亮度反白
set backspace=2         "可隨時用倒退鍵刪除
set autoindent          "自動縮排
set ruler               "可顯示最後一列的狀態
set showmode            "左下角那一列的狀態
set nu                  "可以在每一列的最前面顯示行號啦!
set bg=dark             "顯示不同的底色色調
syntax on               "進行語法檢驗,顏色顯示。

在這個檔案中,使用『 set hlsearch 』或『 :set hlsearch 』,亦即最前面有沒有冒號『 : 』效果都是一樣的! 至於雙引號則是註解符號!不要用錯註解符號,否則每次使用 vim 時都會發生警告訊息喔! 建立好這個檔案後,當你下次重新以 vim 編輯某個檔案時,該檔案的預設環境設定就是上頭寫的囉~ 這樣,是否很方便你的操作啊!多多利用 vim 的環境設定功能呢!^_^



9.3.6 vim 常用指令示意圖

為了方便大家查詢在不同的模式下可以使用的 vim 指令,鳥哥查詢了一些 vim 與 Linux 教育訓練手冊, 發現底下這張圖非常值得大家參考!可以更快速有效的查詢到需要的功能喔!看看吧!

vim 常用指令示意圖
圖9.3.10、vim 常用指令示意圖

9.4 其他 vim 使用注意事項

vim 其實不是那麼好學,雖然他的功能確實非常強大!所以底下我們還有一些需要注意的地方要來跟大家分享喔!

9.4.1 中文編碼的問題

很多朋友常常哀嚎,說他們的 vim 裡面怎麼無法顯示正常的中文啊?其實這很有可能是因為編碼的問題! 因為中文編碼有 big5 與 utf8 兩種,如果你的檔案是使用 big5 編碼製作的,但在 vim 的終端介面中你使用的是萬國碼(utf8), 由於編碼的不同,你的中文檔案內容當然就是一堆亂碼了!怎麼辦?這時你得要考慮許多東西啦!有這些:

  1. 你的 Linux 系統預設支援的語系資料:這與 /etc/locale.conf 有關;
  2. 你的終端介面 (bash) 的語系: 這與 LANG, LC_ALL 這幾個變數有關;
  3. 你的檔案原本的編碼;
  4. 開啟終端機的軟體,例如在 GNOME 底下的視窗介面。

事實上最重要的是上頭的第三與第四點,只要這兩點的編碼一致,你就能夠正確的看到與編輯你的中文檔案。 否則就會看到一堆亂碼啦!

一般來說,中文編碼使用 big5 時,在寫入某些資料庫系統中,在『許、蓋、功』這些字體上面會發生錯誤! 所以近期以來大多希望大家能夠使用萬國碼 utf8 來進行中文編碼!但是在中文 Windows 上的軟體常常預設使用 big5 的編碼 (不一定是 windows 系統的問題,有時候是某些中文軟體的預設值之故), 包括鳥哥由於沿用以前的文件資料檔案,也大多使用 big5 的編碼。此時就得要注意上述的這些咚咚囉。

在 Linux 本機前的 tty1~tty6 原本預設就不支援中文編碼,所以不用考慮這個問題!因為你一定會看到亂碼!呵呵! 現在鳥哥假設俺的文件檔案內編碼為 big5 時,而且我的環境是使用 Linux 的 GNOME ,啟動的終端介面為 GNOME-terminal 軟體, 那鳥哥通常是這樣來修正語系編碼的行為:

[dmtsai@study ~]$ LANG=zh_TW.big5
[dmtsai@study ~]$ export LC_ALL=zh_TW.big5

然後在終端介面工具列的『終端機』-->『設定字元編碼』 -->『中文 (正體) (BIG5)』項目點選一下, 如果一切都沒有問題了,再用 vim 去開啟那個 big5 編碼的檔案,就沒有問題了!以上!報告完畢!



9.4.2 DOS 與 Linux 的斷行字元

我們在第六章裡面談到 cat 這個指令時,曾經提到過 DOS 與 Linux 斷行字元的不同。 而我們也可以利用 cat -A 來觀察以 DOS (Windows 系統) 建立的檔案的特殊格式, 也可以發現在 DOS 使用的斷行字元為 ^M$ ,我們稱為 CR 與 LF 兩個符號。 而在 Linux 底下,則是僅有 LF ($) 這個斷行符號。這個斷行符號對於 Linux 的影響很大喔! 為什麼呢?

我們說過,在 Linux 底下的指令在開始執行時,他的判斷依據是 『Enter』,而 Linux 的 Enter 為 LF 符號, 不過,由於 DOS 的斷行符號是 CRLF ,也就是多了一個 ^M 的符號出來, 在這樣的情況下,如果是一個 shell script 的程式檔案,呵呵~將可能造成『程式無法執行』的狀態~ 因為他會誤判程式所下達的指令內容啊!這很傷腦筋吧!

那怎麼辦啊?很簡單啊,將格式轉換成為 Linux 即可啊!『廢話』,這當然大家都知道,但是, 要以 vi 進入該檔案,然後一個一個刪除每一列的 CR 嗎?當然沒有這麼沒人性啦! 我們可以透過簡單的指令來進行格式的轉換啊!

不過,由於我們要操作的指令預設並沒有安裝,鳥哥也無法預期你有沒有網路,因此假設你沒有網路的狀況下, 請拿出你的原版光碟,放到光碟機裡頭去,然後使用底下的方式來安裝我們所需要的這個軟體喔!

[dmtsai@study ~]$ su -   # 安裝軟體一定要是 root 的權限才行!
[root@study ~]# mount /dev/sr0 /mnt
[root@study ~]# rpm -ivh /mnt/Packages/dos2unix-*
warning: /mnt/Packages/dos2unix-6.0.3-4.el7.x86_64.rpm: Header V3 RSA/SHA256 ....
Preparing...                          ################################# [100%]
Updating / installing...
   1:dos2unix-6.0.3-4.el7             ################################# [100%]
[root@study ~]# umount /mnt
[root@study ~]# exit

那就開始來玩一玩這個字元轉換吧!

[dmtsai@study ~]$ dos2unix [-kn] file [newfile]
[dmtsai@study ~]$ unix2dos [-kn] file [newfile]
選項與參數:
-k  :保留該檔案原本的 mtime 時間格式 (不更新檔案上次內容經過修訂的時間)
-n  :保留原本的舊檔,將轉換後的內容輸出到新檔案,如: dos2unix -n old new

範例一:將 /etc/man_db.conf 重新複製到 /tmp/vitest/ 底下,並將其修改成為 dos 斷行
[dmtsai@study ~]# cd /tmp/vitest
[dmtsai@study vitest]$ cp -a /etc/man_db.conf .
[dmtsai@study vitest]$ ll man_db.conf
-rw-r--r--. 1 root root 5171 Jun 10  2014 man_db.conf
[dmtsai@study vitest]$ unix2dos -k man_db.conf
unix2dos: converting file man_db.conf to DOS format ...
# 螢幕會顯示上述的訊息,說明斷行轉為 DOS 格式了!
[dmtsai@study vitest]$ ll man_db.conf
-rw-r--r--. 1 dmtsai dmtsai 5302 Jun 10  2014 man_db.conf
# 斷行字元多了 ^M ,所以容量增加了!

範例二:將上述的 man_db.conf 轉成 Linux 斷行字元,並保留舊檔,新檔放於 man_db.conf.linux
[dmtsai@study vitest]$ dos2unix -k -n man_db.conf man_db.conf.linux
dos2unix: converting file man_db.conf to file man_db.conf.linux in Unix format ...
[dmtsai@study vitest]$ ll man_db.conf*
-rw-r--r--. 1 dmtsai dmtsai 5302 Jun 10  2014 man_db.conf
-rw-r--r--. 1 dmtsai dmtsai 5171 Jun 10  2014 man_db.conf.linux
[dmtsai@study vitest]$ file man_db.conf*
man_db.conf:       ASCII text, with CRLF line terminators  # 很清楚說明是 CRLF 斷行!
man_db.conf.linux: ASCII text

因為斷行字符以及 DOS 與 Linux 作業系統底下一些字符的定義不同,因此, 不建議你在 Windows 系統當中將檔案編輯好之後,才上傳到 Linux 系統,會容易發生錯誤問題。 而且,如果你在不同的系統之間複製一些純文字檔案時,千萬記得要使用 unix2dos 或 dos2unix 來轉換一下斷行格式啊!



9.4.3 語系編碼轉換

很多朋友都會有的問題,就是想要將語系編碼進行轉換啦!舉例來說,想要將 big5 編碼轉成 utf8 。 這個時候怎麼辦?難不成要每個檔案打開會轉存成 utf8 嗎?不需要這樣做啦!使用 iconv 這個指令即可! 鳥哥將之前的 vi 章節做成 big5 編碼的檔案,你可以照底下的連結來下載先:

在終端機的環境下你可以使用『 wget 網址』來下載上述的檔案喔!鳥哥將他下載在 /tmp/vitest 目錄下。 接下來讓我們來使用 iconv 這個指令來玩一玩編碼轉換吧!

[dmtsai@study ~]$ iconv --list
[dmtsai@study ~]$ iconv -f 原本編碼 -t 新編碼 filename [-o newfile]
選項與參數:
--list :列出 iconv 支援的語系資料
-f     :from ,亦即來源之意,後接原本的編碼格式;
-t     :to ,亦即後來的新編碼要是什麼格式;
-o file:如果要保留原本的檔案,那麼使用 -o 新檔名,可以建立新編碼檔案。

範例一:將 /tmp/vitest/vi.big5 轉成 utf8 編碼吧!
[dmtsai@study ~]$ cd /tmp/vitest
[dmtsai@study vitest]$ iconv -f big5 -t utf8 vi.big5 -o vi.utf8
[dmtsai@study vitest]$ file vi*
vi.big5: ISO-8859 text, with CRLF line terminators
vi.utf8: UTF-8 Unicode text, with CRLF line terminators
# 是吧!有明顯的不同吧! ^_^

這指令支援的語系非常之多,除了正體中文的 big5, utf8 編碼之外,也支援簡體中文的 gb2312 , 所以對岸的朋友可以簡單的將鳥站的網頁資料下載後,利用這個指令來轉成簡體,就能夠輕鬆的讀取文件資料囉! 不過,不要將轉成簡體的檔案又上傳成為您自己的網頁啊!這明明是鳥哥寫的不是嗎? ^_^

不過如果是要將正體中文的 utf8 轉成簡體中文的 utf8 編碼時,那就得費些功夫了! 舉例來說,如果要將剛剛那個 vi.utf8 轉成簡體的 utf8 時,可以這樣做:

[dmtsai@study vitest]$ iconv -f utf8 -t big5 vi.utf8 | \
> iconv -f big5 -t gb2312 | iconv -f gb2312 -t utf8 -o vi.gb.utf8

9.5 重點回顧

  • Linux 底下的設定檔多為文字檔,故使用 vim 即可進行設定編輯;
  • vim 可視為程式編輯器,可用以編輯 shell script, 設定檔等,避免打錯字;
  • vi 為所有 unix like 的作業系統都會存在的編輯器,且執行速度快速;
  • vi 有三種模式,一般指令模式可變換到編輯與指令列模式,但編輯模式與指令列模式不能互換;
  • 常用的按鍵有i, [Esc], :wq 等;
  • vi 的畫面大略可分為兩部份,(1)上半部的本文與(2)最後一行的狀態+指令列模式;
  • 數字是有意義的,用來說明重複進行幾次動作的意思,如 5yy 為複製 5 列之意;
  • 游標的移動中,大寫的 G 經常使用,尤其是 1G, G 移動到文章的頭/尾功能!
  • vi 的取代功能也很棒! :n1,n2s/old/new/g 要特別注意學習起來;
  • 小數點『 . 』為重複進行前一次動作,也是經常使用的按鍵功能!
  • 進入編輯模式幾乎只要記住: i, o, R 三個按鈕即可!尤其是新增一列的 o 與取代的 R
  • vim 會主動的建立 swap 暫存檔,所以不要隨意斷線!
  • 如果在文章內有對齊的區塊,可以使用 [ctrl]-v 進行複製/貼上/刪除的行為
  • 使用 :sp 功能可以分割視窗
  • 若使用 vim 來撰寫網頁,若需要 CSS 元素資料,可透過 [ctrl]+x, [ctrl]+o 這兩個連續組合按鍵來取得關鍵字
  • vim 的環境設定可以寫入在 ~/.vimrc 檔案中;
  • 可以使用 iconv 進行檔案語系編碼的轉換
  • 使用 dos2unix 及 unix2dos 可以變更檔案每一列的行尾斷行字元。

9.6 本章練習

(要看答案請將滑鼠移動到『答:』底下的空白處,按下左鍵圈選空白處即可察看) 實作題部分:
  • 在第七章的情境模擬題二的第五點,編寫 /etc/fstab 時,當時使用 nano 這個指令, 請嘗試使用 vim 去編輯 /etc/fstab ,並且將第七章新增的那一列的 defatuls 改成 default ,會出現什麼狀態? 離開前請務必要修訂成原本正確的資訊。此外,如果將該列註解 (最前面加 #),你會發現字體顏色也有變化喔!

  • 嘗試在你的系統中,你慣常使用的那個帳號的家目錄下,將本章介紹的 vimrc 內容進行一些常用設定,包括:
    • 設定搜尋高亮度反白
    • 設定語法檢驗啟動
    • 設定預設啟動行號顯示
    • 設定有兩行狀態列 (一行狀態+一行指令列) :set laststatus=2

簡答題部分:
  • 我用 vi 開啟某個檔案後,要在第 34 列向右移動 15 個字元,應該在一般指令模式中下達什麼指令?
    (1)先按下 34G 到第 34 列;(2)再按下 [ 15 + 向右鍵 ],或 [ 15l ] 亦可!
  • 在 vi 開啟的檔案中,如何去到該檔案的頁首或頁尾?
    去頁首按下 1G 或 gg ;去頁尾按下 G 即可
  • 在 vi 開啟的檔案中,如何在游標所在列中,移動到行頭及行尾?
    移動到行頭,按 0 ,移動到行尾按 $ 即可!
  • vi 的一般指令模式情況下,按下『 r 』有什麼功能?
    取代游標所在的那個字元
  • 在 vi 的環境中,如何將目前正在編輯的檔案另存新檔名為 newfilename?
    :w newfilename
  • 在 linux 底下最常使用的文書編輯器為 vi ,請問如何進入編輯模式?
    在一般指令模式底下輸入: i, I, a, A 為在本列當中輸入新字元;(出現 –Insert- )
    在一般指令模式當中輸入: o, O 為在一個新的一列輸入新字元;
    在一般指令模式當中輸入: r, R 為取代字元!(左下角出現 –Replace-)
  • 在 vi 軟體中,如何由編輯模式跳回一般指令模式?
    可以按下[Esc]
  • 在 vi 環境中,若上下左右鍵無法使用時,請問如何在一般指令模式移動游標?
    [h, j, k, l]分別代表[左、下、上、右]
  • 在 vi 的一般指令模式中,如何刪除一列、n列;如何刪除一個字元?
    分別為 dd, ndd, x 或 X (dG 及 d1G 分別表示刪除到頁首及頁尾)
  • 在 vi 的一般指令模式中,如何複製一列、n列並加以貼上?
    分別為 yy, nyy, p 或 P
  • 在 vi 的一般指令模式中如何搜尋 string 這個字串?
    ?string (往前搜尋)
    /string (往後搜尋)
  • 在 vi 的一般指令模式中,如何取代 word1 成為 word2,而若需要使用者確認機制,又該如何?
    :1,$s/word1/word2/g 或
    :1,$s/word1/word2/gc (需要使用者確認)
  • 在 vi 目前的編輯檔案中,在一般指令模式下,如何讀取一個檔案 filename 進來目前這個檔案?
    :r filename
  • 在 vi 的一般指令模式中,如何存檔、離開、存檔後離開、強制存檔後離開?
    :w; :q: :wq; :wq!
  • 在 vi 底下作了很多的編輯動作之後,卻想還原成原來的檔案內容,應該怎麼進行?
    直接按下 :e! 即可恢復成檔案的原始狀態!
  • 我在 vi 這個程式當中,不想離開 vi ,但是想執行 ls /home 這個指令,vi 有什麼額外的功能可以達到這個目的:
    事實上,可以使用[ :! ls /home ]不過,如果你學過後面的章節之後,你會發現,執行[ ctrl + z ]亦可暫時退出 vi 讓你在指令列模式當中執行指令喔!

9.7 參考資料與延伸閱讀

2002/04/05:第一次完成
2003/02/07:重新編排與加入 FAQ
2003/02/25:新加入本章節與 LPI 的相關性說明!
2005/07/28:將舊文章移動到 這裡
2005/08/01:加入果正兄文章的參考,還有查閱 vim 官方網站的資料!
2008/12/18:將原本針對 FC4 版本的文章移動到 此處
2009/01/13:這麼簡單的一篇改寫,竟改了一個月!原因只是期末考將近太忙了~
2009/08/20:加入實作題,編輯簡答題,加入 vim 指令示意圖等
2002/01/21以來統計人數
>>
HOME
PrePage
NextPage
   http://linux.vbird.org is designed by VBird during 2001-2015.