有一個(gè)古老的笑話,說(shuō)是一個(gè)在紐約的游客向行人打聽(tīng)這座城市中著名古典音樂(lè)場(chǎng)館的方向:
游客: 請(qǐng)問(wèn)一下,我怎樣去卡內(nèi)基音樂(lè)大廳?
行人: 練習(xí),練習(xí),練習(xí)!
學(xué)習(xí) Linux 命令行,就像要成為一名造詣很深的鋼琴家一樣,它不是我們一下午就能學(xué)會(huì)的技能。這需要 經(jīng)歷幾年的勤苦練習(xí)。在這一章中,我們將介紹 vi(發(fā)音“vee eye”)文本編輯器,它是 Unix 傳統(tǒng)中核心程序之一。 vi 因它難用的用戶(hù)界面而有點(diǎn)聲名狼藉,但是當(dāng)我們看到一位大師坐在鋼琴前開(kāi)始演奏時(shí),我們的確成了 偉大藝術(shù)的見(jiàn)證人。雖然我們?cè)谶@里不能成為 vi 大師,但是當(dāng)我們學(xué)完這一章后, 我們會(huì)知道怎樣在 vi 中玩“筷子”。
在現(xiàn)在這個(gè)圖形編輯器和易于使用的基于文本編輯器的時(shí)代,比如說(shuō) nano,為什么我們還應(yīng)該學(xué)習(xí) vi 呢? 下面有三個(gè)充分的理由:
vi 很多系統(tǒng)都預(yù)裝。如果我們的系統(tǒng)沒(méi)有圖形界面,比方說(shuō)一臺(tái)遠(yuǎn)端服務(wù)器或者是一個(gè) X 配置損壞了的本地系統(tǒng),那么 vi 就成了我們的救星。雖然 nano 逐漸流行起來(lái),但是它 還沒(méi)有普及。POSIX,這套 Unix 系統(tǒng)中程序兼容的標(biāo)準(zhǔn),就要求系統(tǒng)要預(yù)裝 vi。
vi 是輕量級(jí)且執(zhí)行快速的編輯器。對(duì)于許多任務(wù)來(lái)說(shuō),啟動(dòng) vi 比起在菜單中找到一個(gè)圖形化文本編輯器, 再等待編輯器數(shù)倍兆字節(jié)的數(shù)據(jù)加載而言,要容易的多。另外,vi 是為了加快輸入速度而設(shè)計(jì)的。 我們將會(huì)看到,當(dāng)一名熟練的 vi 用戶(hù)在編輯文件時(shí),他或她的手從不需要移開(kāi)鍵盤(pán)。
好吧,可能只有兩個(gè)充分的理由。
第一版 vi 是在1976由 Bill Joy 寫(xiě)成的,當(dāng)時(shí)他是加州大學(xué)伯克利分校的學(xué)生, 后來(lái)他共同創(chuàng)建了 Sun 微系統(tǒng)公司。vi 這個(gè)名字 來(lái)源于單詞“visual”,因?yàn)樗蛩阍趲в锌梢苿?dòng)光標(biāo)的視頻終端上編輯文本。在發(fā)明可視化編輯器之前, 有一次只能操作一行文本的行編輯器。為了指定一個(gè)修改,我們告訴行編輯器到一個(gè)特殊行并且 說(shuō)明做什么修改,比方說(shuō)添加或刪除文本。視頻終端(而不是基于打印機(jī)的終端,像電傳打印機(jī))的出現(xiàn) ,可視化編輯成為可能。vi 實(shí)際上整合了一個(gè)強(qiáng)大的叫做 ex 行編輯器, 所以我們?cè)谑褂?vi 時(shí)能運(yùn)行行編輯命令。
大多數(shù) Linux 發(fā)行版不包含真正的 vi;而是自帶一款高級(jí)替代版本,叫做 vim(它是“vi improved”的簡(jiǎn)寫(xiě))由 Bram Moolenaar 開(kāi)發(fā)的。vim 相對(duì)于傳統(tǒng)的 Unix vi 來(lái)說(shuō),取得了實(shí)質(zhì)性進(jìn)步。通常,vim 在 Linux 系統(tǒng)中是“vi”的符號(hào)鏈接(或別名)。 在隨后的討論中,我們將會(huì)假定我們有一個(gè)叫做“vi”的程序,但它其實(shí)是 vim。
要想啟動(dòng) vi,只要簡(jiǎn)單地輸入以下命令:
[me@linuxbox ~]$ vi
一個(gè)像這樣的屏幕應(yīng)該出現(xiàn):
VIM - Vi Improved
....
正如我們之前操作 nano 時(shí),首先要學(xué)的是怎樣退出 vi。要退出 vi,輸入下面的命令(注意冒號(hào)是命令的一部分):
:q
shell 提示符應(yīng)該返回。如果由于某種原因,vi 不能退出(通常因?yàn)槲覀儗?duì)文件做了修改,卻沒(méi)有保存文件)。 通過(guò)給命令加上嘆號(hào),我們可以告訴 vi 我們真要退出 vi。
:q!
小貼示:如果你在 vi 中“迷失”了,試著按下 Esc 鍵兩次來(lái)找到路(回到普通模式)。
兼容模式
上面實(shí)例中的啟動(dòng)屏幕(來(lái)自于 Ubuntu 8.04),我們看到一行文字“以 Vi 兼容的模式運(yùn)行”。這意味著 vim 將以近似于 vi 常規(guī)的模式 運(yùn)行,而不是 vim 的高級(jí)規(guī)范。為了這章的目的,我們想要使用 vim 的高級(jí)規(guī)范。要想這樣做, 你有幾個(gè)選擇:
用 vim 來(lái)代替 vi。
如果命令生效,考慮在你的.bashrc 文件中添加別名 vi='vim'。
或者,使用這個(gè)命令在你的 vim 配置文件中添加一行:
echo "set nocp" >> ~/.vimrc
不同的 Linux 發(fā)行版其 vim 軟件包也迥然不同。一些發(fā)行版只是安裝了 vim 的最小版本, 其默認(rèn)只支持有限的 vim 特性。當(dāng)練習(xí)隨后的課程時(shí),你可能會(huì)遇到缺失的功能。 如果是這種情況,就安裝 vim 的完整版。
再次啟動(dòng) vi,這次傳遞給 vi 一個(gè)不存在的文件名。這也是用 vi 創(chuàng)建新文件的方法。
[me@linuxbox ~]$ rm -f foo.txt
[me@linuxbox ~]$ vi foo.txt
如果一切運(yùn)行正常,我們應(yīng)該獲得一個(gè)像這樣的屏幕:
....
"foo.txt" [New File]
每行開(kāi)頭的波浪號(hào)("~")指示那一行不存在文本。這表示我們有一個(gè)空文件。還沒(méi)有輸入任何字符?
學(xué)習(xí) vi 時(shí),要知道的第二件非常重要的事情是(知道了如何退出 vi 后)vi 是一個(gè)模式編輯器。當(dāng) vi 啟動(dòng)后,進(jìn)入 的是命令模式。這種模式下,幾乎每個(gè)按鍵都是一個(gè)命令,所以如果我們打算輸入字符,vi 會(huì)發(fā)瘋,弄得一團(tuán)糟。
為了在文件中添加文本,首先我們必須進(jìn)入插入模式。按下"i"按鍵進(jìn)入插入模式。之后,我們應(yīng)該 在屏幕底部看到下面一行,如果 vi 運(yùn)行在高級(jí)模式下(這不會(huì)出現(xiàn)在 vi 兼容模式下):
-- INSERT --
現(xiàn)在我們能輸入一些文本了。試著輸入這些文本:
The quick brown fox jumped over the lazy dog.
按下 Esc 按鍵,退出插入模式并返回命令模式。
為了保存我們剛才對(duì)文件所做的修改,我們必須在命令模式下輸入一個(gè) ex 命令。 通過(guò)按下":"鍵,這很容易完成。按下冒號(hào)鍵之后,一個(gè)冒號(hào)字符應(yīng)該出現(xiàn)在屏幕的底部:
:
為了寫(xiě)入我們修改的文件,我們?cè)诿疤?hào)之后輸入"w"字符,然后按下回車(chē)鍵:
:w
文件將會(huì)寫(xiě)入到硬盤(pán),并且我們應(yīng)該在屏幕底部得到一個(gè)確認(rèn)信息,就像這樣:
"foo.txt" [New] 1L, 46C written
小貼示:如果你閱讀 vim 的文檔,你注意到(混淆地)命令模式被叫做普通模式,ex 命令 叫做命令模式。當(dāng)心。
當(dāng)在 vi 命令模式下時(shí),vi 提供了大量的移動(dòng)命令,其中一些是與 less 閱讀器共享的。這里 列舉了一些:
按鍵 | 移動(dòng)光標(biāo) |
---|---|
l or 右箭頭 | 向右移動(dòng)一個(gè)字符 |
h or 左箭頭 | 向左移動(dòng)一個(gè)字符 |
j or 下箭頭 | 向下移動(dòng)一行 |
k or 上箭頭 | 向上移動(dòng)一行 |
0 (零按鍵) | 移動(dòng)到當(dāng)前行的行首。 |
^ | 移動(dòng)到當(dāng)前行的第一個(gè)非空字符。 |
$ | 移動(dòng)到當(dāng)前行的末尾。 |
w | 移動(dòng)到下一個(gè)單詞或標(biāo)點(diǎn)符號(hào)的開(kāi)頭。 |
W | 移動(dòng)到下一個(gè)單詞的開(kāi)頭,忽略標(biāo)點(diǎn)符號(hào)。 |
b | 移動(dòng)到上一個(gè)單詞或標(biāo)點(diǎn)符號(hào)的開(kāi)頭。 |
B | 移動(dòng)到上一個(gè)單詞的開(kāi)頭,忽略標(biāo)點(diǎn)符號(hào)。 |
Ctrl-f or Page Down | 向下翻一頁(yè) |
Ctrl-b or Page Up | 向上翻一頁(yè) |
numberG | 移動(dòng)到第 number 行。例如,1G 移動(dòng)到文件的第一行。 |
G | 移動(dòng)到文件末尾。 |
為什么 h,j,k,和 l 按鍵被用來(lái)移動(dòng)光標(biāo)呢?因?yàn)樵陂_(kāi)發(fā) vi 之初,并不是所有的視頻終端都有 箭頭按鍵,熟練的打字員可以使用規(guī)則的鍵盤(pán)按鍵來(lái)移動(dòng)光標(biāo),他們的手從不需要移開(kāi)鍵盤(pán)。
vi 中的許多命令都可以在前面加上一個(gè)數(shù)字,比方說(shuō)上面提到的"G"命令。在命令之前加上一個(gè) 數(shù)字,我們就可以指定命令執(zhí)行的次數(shù)。例如,命令"5j"導(dǎo)致 vi 向下移動(dòng)5行。
大多數(shù)編輯工作由一些基本的操作組成,比如說(shuō)插入文本,刪除文本和通過(guò)剪切和粘貼來(lái)移動(dòng)文本。 vi,當(dāng)然,以它自己的獨(dú)特方式來(lái)支持所有的操作。vi 也提供了有限的撤銷(xiāo)形式。如果我們按下“u” 按鍵,當(dāng)在命令模式下,vi 將會(huì)撤銷(xiāo)你所做的最后一次修改。當(dāng)我們?cè)囍鴪?zhí)行一些基本的 編輯命令時(shí),這會(huì)很方便。
vi 有幾種不同進(jìn)入插入模式的方法。我們已經(jīng)使用了 i 命令來(lái)插入文本。
讓我們返回到我們的 foo.txt 文件中,呆一會(huì)兒:
The quick brown fox jumped over the lazy dog.
如果我們想要在這個(gè)句子的末尾添加一些文本,我們會(huì)發(fā)現(xiàn) i 命令不能完成任務(wù),因?yàn)槲覀儾荒馨?光標(biāo)移到行尾。vi 提供了追加文本的命令,明智地命名為"a"命令。如果我們把光標(biāo)移動(dòng)到行尾,輸入"a", 光標(biāo)就會(huì)越過(guò)行尾,vi 進(jìn)入插入模式。這樣就允許我們添加更多的文本:
The quick brown fox jumped over the lazy dog. It was cool.
記住按下 Esc 按鍵來(lái)退出插入模式。
因?yàn)槲覀儙缀蹩偸窍胍谛形哺郊游谋荆?vi 提供了一種快捷方式來(lái)移動(dòng)到當(dāng)前行的末尾,并且能添加 文本。它是"A"命令。試著用一下它,給文件添加更多行。
首先,使用"0"(零)命令,將光標(biāo)移動(dòng)到行首。現(xiàn)在我們輸入"A",來(lái)添加以下文本行:
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
再一次,按下 Esc 按鍵退出插入模式。
正如我們所看到的,大 A 命令非常有用,因?yàn)樵趩?dòng)插入模式之前,它把光標(biāo)移到了行尾。
我們插入文本的另一種方式是“打開(kāi)”一行。這會(huì)在存在的兩行之間插入一個(gè)空白行,并且進(jìn)入插入模式。 這種方式有兩個(gè)變體:
命令 | 打開(kāi)行 |
---|---|
o | 當(dāng)前行的下方打開(kāi)一行。 |
O | 當(dāng)前行的上方打開(kāi)一行。 |
我們可以演示一下:把光標(biāo)放到"Line 3"上,按下小 o 按鍵。
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
line 4
line 5
在第三行之下打開(kāi)了新的一行,并且進(jìn)入插入模式。按下 Esc,退出插入模式。按下 u 按鍵,撤銷(xiāo)我們的修改。
按下大 O 按鍵在光標(biāo)之上打開(kāi)新的一行:
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
按下 Esc 按鍵,退出插入模式,并且按下 u 按鍵,撤銷(xiāo)我們的更改。
正如我們期望的,vi 提供了各種各樣的方式來(lái)刪除文本,所有的方式包含一個(gè)或兩個(gè)按鍵。首先, x 按鍵會(huì)刪除光標(biāo)位置的一個(gè)字符??梢栽?x 命令之前帶上一個(gè)數(shù)字,來(lái)指明要?jiǎng)h除的字符個(gè)數(shù)。 d 按鍵更通用一些。類(lèi)似 x 命令,d 命令之前可以帶上一個(gè)數(shù)字,來(lái)指定要執(zhí)行的刪除次數(shù)。另外, d 命令之后總是帶上一個(gè)移動(dòng)命令,用來(lái)控制刪除的范圍。這里有些實(shí)例:
命令 | 刪除的文本 |
---|---|
x | 當(dāng)前字符 |
3x | 當(dāng)前字符及其后的兩個(gè)字符。 |
dd | 當(dāng)前行。 |
5dd | 當(dāng)前行及隨后的四行文本。 |
dW | 從光標(biāo)位置開(kāi)始到下一個(gè)單詞的開(kāi)頭。 |
d$ | 從光標(biāo)位置開(kāi)始到當(dāng)前行的行尾。 |
d0 | 從光標(biāo)位置開(kāi)始到當(dāng)前行的行首。 |
d^ | 從光標(biāo)位置開(kāi)始到文本行的第一個(gè)非空字符。 |
dG | 從當(dāng)前行到文件的末尾。 |
d20G | 從當(dāng)前行到文件的第20行。 |
把光標(biāo)放到第一行單詞“It”之上。重復(fù)按下 x 按鍵直到刪除剩下的部分。下一步,重復(fù)按下 u 按鍵 直到恢復(fù)原貌。
注意:真正的 vi 只是支持單層面的 undo 命令。vim 則支持多個(gè)層面的。
我們?cè)俅螆?zhí)行刪除命令,這次使用 d 命令。還是移動(dòng)光標(biāo)到單詞"It"之上,按下的 dW 來(lái)刪除單詞:
The quick brown fox jumped over the lazy dog. was cool.
Line 2
Line 3
Line 4
Line 5
按下 d$刪除從光標(biāo)位置到行尾的文本:
The quick brown fox jumped over the lazy dog.
Line 2
Line 3
Line 4
Line 5
按下 dG 按鍵刪除從當(dāng)前行到文件末尾的所有行:
~
....
連續(xù)按下 u 按鍵三次,來(lái)恢復(fù)刪除部分。
這個(gè) d 命令不僅刪除文本,它還“剪切”文本。每次我們使用 d 命令,刪除的部分被復(fù)制到一個(gè) 粘貼緩沖區(qū)中(看作剪切板)。過(guò)后我們執(zhí)行小 p 命令把剪切板中的文本粘貼到光標(biāo)位置之后, 或者是大 P 命令把文本粘貼到光標(biāo)之前。
y 命令用來(lái)“拉”(復(fù)制)文本,和 d 命令剪切文本的方式差不多。這里有些把 y 命令和各種移動(dòng)命令 結(jié)合起來(lái)使用的實(shí)例:
命令 | 復(fù)制的內(nèi)容 |
---|---|
yy | 當(dāng)前行。 |
5yy | 當(dāng)前行及隨后的四行文本。 |
yW | 從當(dāng)前光標(biāo)位置到下一個(gè)單詞的開(kāi)頭。 |
y$ | 從當(dāng)前光標(biāo)位置到當(dāng)前行的末尾。 |
y0 | 從當(dāng)前光標(biāo)位置到行首。 |
y^ | 從當(dāng)前光標(biāo)位置到文本行的第一個(gè)非空字符。 |
yG | 從當(dāng)前行到文件末尾。 |
y20G | 從當(dāng)前行到文件的第20行。 |
我們?cè)囍鲂?fù)制和粘貼工作。把光標(biāo)放到文本第一行,輸入 yy 來(lái)復(fù)制當(dāng)前行。下一步,把光標(biāo)移到 最后一行(G),輸入小寫(xiě)的 p 把復(fù)制的一行粘貼到當(dāng)前行的下面:
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
The quick brown fox jumped over the lazy dog. It was cool.
和以前一樣,u 命令會(huì)撤銷(xiāo)我們的修改。光標(biāo)仍然位于文件的最后一行,輸入大寫(xiě)的 P 命令把 所復(fù)制的文本粘貼到當(dāng)前行之上:
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
The quick brown fox jumped over the lazy dog. It was cool.
試著執(zhí)行上表中一些其他的 y 命令,了解小寫(xiě) p 和大寫(xiě) P 命令的行為。當(dāng)你完成練習(xí)之后,把文件 恢復(fù)原樣。
vi 對(duì)于行的概念相當(dāng)嚴(yán)格。通常,不可能把光標(biāo)移到行尾,再刪除行尾結(jié)束符(回車(chē)符)來(lái)連接 當(dāng)前行和它下面的一行。由于這個(gè)原因,vi 提供了一個(gè)特定的命令,大寫(xiě)的 J(不要與小寫(xiě)的 j 混淆了, j 是用來(lái)移動(dòng)光標(biāo)的)把行與行之間連接起來(lái)。
如果我們把光標(biāo)放到 line 3上,輸入大寫(xiě)的 J 命令,看看發(fā)生什么情況:
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3 Line 4
Line 5
vi 有能力把光標(biāo)移到搜索到的匹配項(xiàng)上。vi 可以在單一行或整個(gè)文件中運(yùn)用這個(gè)功能。 它也可以在有或沒(méi)有用戶(hù)確認(rèn)的情況下實(shí)現(xiàn)文本替換。
f 命令查找一行,移動(dòng)光標(biāo)到下一個(gè)所指定的字符上。例如,命令 fa 會(huì)把光標(biāo)定位到同一行中 下一個(gè)出現(xiàn)的"a"字符上。在一行中執(zhí)行了字符的查找命令之后,通過(guò)輸入分號(hào)來(lái)重復(fù)這個(gè)查找。
移動(dòng)光標(biāo)到下一個(gè)出現(xiàn)的單詞或短語(yǔ)上,使用 / 命令。這個(gè)命令和我們之前在 less 程序中學(xué)到 的一樣。當(dāng)你輸入/命令后,一個(gè)"/"字符會(huì)出現(xiàn)在屏幕底部。下一步,輸入要查找的單詞或短語(yǔ)后, 按下回車(chē)。光標(biāo)就會(huì)移動(dòng)到下一個(gè)包含所查找字符串的位置。通過(guò) n 命令來(lái)重復(fù)先前的查找。 這里有個(gè)例子:
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
把光標(biāo)移動(dòng)到文件的第一行。輸入:
/Line
然后鍵入回車(chē)。光標(biāo)會(huì)移動(dòng)到第二行。下一步,輸入 n,光標(biāo)移到第三行。重復(fù)這個(gè) n 命令,光標(biāo)會(huì) 繼續(xù)向下移動(dòng)直到遍歷了所有的匹配項(xiàng)。雖然目前,我們只是使用了單詞和短語(yǔ)來(lái)作為我們的查找 模式,但是 vi 允許使用正則表達(dá)式,一種強(qiáng)大的用來(lái)表示復(fù)雜文本模式的方法。我們將會(huì)在隨后 的章節(jié)里面詳盡地介紹正則表達(dá)式。
vi 使用 ex 命令來(lái)執(zhí)行查找和替代操作(vi 中叫做“替換”)。把整個(gè)文件中的單詞“Line”更改為“l(fā)ine”, 我們輸入以下命令:
:%s/Line/line/g
我們把這個(gè)命令分解為幾個(gè)單獨(dú)的部分,看一下每部分的含義:
條目 | 含義 |
---|---|
: | 冒號(hào)字符運(yùn)行一個(gè) ex 命令。 |
% | 指定要操作的行數(shù)。% 是一個(gè)快捷方式,表示從第一行到最后一行。另外,操作范圍也 可以用 1,5 來(lái)代替(因?yàn)槲覀兊奈募挥?行文本),或者用 1,$ 來(lái)代替,意思是 “ 從第一行到文件的最后一行?!?如果省略了文本行的范圍,那么操作只對(duì)當(dāng)前行生效。 |
s | 指定操作。在這種情況下是,替換(查找與替代)。 |
/Line/line | 查找類(lèi)型與替代文本。 |
g | 這是“全局”的意思,意味著對(duì)文本行中所有匹配的字符串執(zhí)行查找和替換操作。如果省略 g,則 只替換每個(gè)文本行中第一個(gè)匹配的字符串。 |
執(zhí)行完查找和替代命令之后,我們的文件看起來(lái)像這樣:
The quick brown fox jumped over the lazy dog. It was cool.
line 2
line 3
line 4
line 5
我們也可以指定一個(gè)需要用戶(hù)確認(rèn)的替換命令。通過(guò)添加一個(gè)"c"字符到這個(gè)命令的末尾,來(lái)完成 這個(gè)替換命令。例如:
:%s/line/Line/gc
這個(gè)命令會(huì)把我們的文件恢復(fù)先前的模樣;然而,在執(zhí)行每個(gè)替換命令之前,vi 會(huì)停下來(lái), 通過(guò)下面的信息,來(lái)要求我們確認(rèn)這個(gè)替換:
replace with Line (y/n/a/q/l/^E/^Y)?
括號(hào)中的每個(gè)字符都是一個(gè)可能的選擇,如下所示:
按鍵 | 行為 |
---|---|
y | 執(zhí)行替換操作 |
n | 跳過(guò)這個(gè)匹配的實(shí)例 |
a | 對(duì)這個(gè)及隨后所有匹配的字符串執(zhí)行替換操作。 |
q or esc | 退出替換操作。 |
l | 執(zhí)行這次替換并退出。l 是 “l(fā)ast” 的簡(jiǎn)寫(xiě)。 |
Ctrl-e, Ctrl-y | 分別是向下滾動(dòng)和向上滾動(dòng)。用于查看建議替換的上下文。 |
如果你輸入 y,則執(zhí)行這個(gè)替換,輸入 n 則會(huì)導(dǎo)致 vi 跳過(guò)這個(gè)實(shí)例,而移到下一個(gè)匹配項(xiàng)上。
同時(shí)能夠編輯多個(gè)文件是很有用的。你可能需要更改多個(gè)文件或者從一個(gè)文件復(fù)制內(nèi)容到 另一個(gè)文件。通過(guò) vi,我們可以打開(kāi)多個(gè)文件來(lái)編輯,只要在命令行中指定要編輯的文件名。
vi file1 file2 file3...
我們先退出已經(jīng)存在的 vi 會(huì)話,然后創(chuàng)建一個(gè)新文件來(lái)編輯。輸入:wq 來(lái)退出 vi 并且保存了所做的修改。 下一步,我們將在家目錄下創(chuàng)建一個(gè)額外的用來(lái)玩耍的文件。通過(guò)獲取從 ls 命令的輸出,來(lái)創(chuàng)建這個(gè)文件。
[me@linuxbox ~]$ ls -l /usr/bin > ls-output.txt
用 vi 來(lái)編輯我們的原文件和新創(chuàng)建的文件:
[me@linuxbox ~]$ vi foo.txt ls-output.txt
vi 啟動(dòng),我們會(huì)看到第一個(gè)文件顯示出來(lái):
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
從這個(gè)文件轉(zhuǎn)到下一個(gè)文件,使用這個(gè) ex 命令:
:n
回到先前的文件使用:
:N
當(dāng)我們從一個(gè)文件移到另一個(gè)文件時(shí),如果當(dāng)前文件沒(méi)有保存修改,vi 會(huì)阻止我們轉(zhuǎn)換文件, 這是 vi 強(qiáng)制執(zhí)行的政策。在命令之后添加感嘆號(hào),可以強(qiáng)迫 vi 放棄修改而轉(zhuǎn)換文件。
另外,上面所描述的轉(zhuǎn)換方法,vim(和一些版本的 vi)也提供了一些 ex 命令,這些命令使 多個(gè)文件更容易管理。我們可以查看正在編輯的文件列表,使用:buffers 命令。運(yùn)行這個(gè) 命令后,屏幕頂部就會(huì)顯示出一個(gè)文件列表:
:buffers
1 # "foo.txt" line 1
2 %a "ls-output.txt" line 0
Press ENTER or type command to continue
注意:你不同通過(guò):n 或:N 命令在由:e 命令加載的文件之間進(jìn)行切換。這時(shí)要使用:buffer 命令, 其后加上緩沖區(qū)號(hào)碼,來(lái)轉(zhuǎn)換文件。
當(dāng)我們編輯多個(gè)文件時(shí),經(jīng)常地要復(fù)制文件的一部分到另一個(gè)正在編輯的文件。使用之前我們學(xué)到的 拉(yank)和粘貼命令,這很容易完成。說(shuō)明如下。以打開(kāi)的兩個(gè)文件為例,首先轉(zhuǎn)換到緩沖區(qū)1(foo.txt) ,輸入:
:buffer 1
我們應(yīng)該得到以下輸出:
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
下一步,把光標(biāo)移到第一行,并且輸入 yy 來(lái)復(fù)制這一行。
轉(zhuǎn)換到第二個(gè)緩沖區(qū),輸入:
:buffer 2
現(xiàn)在屏幕會(huì)包含一些文件列表(這里只列出了一部分):
total 343700
-rwxr-xr-x 1 root root 31316 2007-12-05 08:58 [
....
移動(dòng)光標(biāo)到第一行,輸入 p 命令把我們從前面文件中復(fù)制的一行粘貼到這個(gè)文件中:
total 343700
The quick brown fox jumped over the lazy dog. It was cool.
-rwxr-xr-x 1 root root 31316 2007-12-05 08:58 [
....
也有可能把整個(gè)文件插入到我們所編輯的文件中。看一下實(shí)際操作,結(jié)束 vi 會(huì)話,重新 啟動(dòng)一個(gè)只打開(kāi)一個(gè)文件的 vi 會(huì)話:
[me@linuxbox ~]$ vi ls-output.txt
再一次看到我們的文件列表:
total 343700
-rwxr-xr-x 1 root root 31316 2007-12-05 08:58 [
移動(dòng)光標(biāo)到第三行,然后輸入以下 ex 命令:
:r foo.txt
這個(gè):r 命令(是"read"的簡(jiǎn)稱(chēng))把指定的文件插入到光標(biāo)位置之前。現(xiàn)在屏幕應(yīng)該看起來(lái)像這樣:
total 343700
-rwxr-xr-x 1 root root 31316 2007-12-05 08:58 [
....
The quick brown fox jumped over the lazy dog. It was cool.
Line 2
Line 3
Line 4
Line 5
-rwxr-xr-x 1 root root 111276 2008-01-31 13:36 a2p
....
像 vi 中的其它操作一樣,有幾種不同的方法來(lái)保存我們所修改的文件。我們已經(jīng)研究了:w 這個(gè) ex 命令, 但還有幾種方法,可能我們也覺(jué)得有幫助。
在命令模式下,輸入 ZZ 就會(huì)保存并退出當(dāng)前文件。同樣地,ex 命令:wq 把:w 和:q 命令結(jié)合到 一起,來(lái)完成保存和退出任務(wù)。
這個(gè):w 命令也可以指定可選的文件名。這個(gè)的作用就如"Save As..."。例如,如果我們 正在編輯 foo.txt 文件,想要保存一個(gè)副本,叫做 foo1.txt,那么我們可以執(zhí)行以下命令:
:w foo1.txt
注意:當(dāng)上面的命令以一個(gè)新名字保存文件時(shí),但它并沒(méi)有更改你正在編輯的文件的名字。 如果你繼續(xù)編輯的話,你還是在編輯文件 foo.txt,而不是 foo1.txt。
即使把這章所學(xué)的內(nèi)容都加起來(lái),我們也只是學(xué)了 vi 和 vim 的一點(diǎn)兒皮毛而已。這里 有一些在線的資料,你可以用來(lái)繼續(xù) vi 學(xué)習(xí)之旅。
學(xué)習(xí) vi 編輯器-一本來(lái)自于 Wikipedia 的 Wikibook,是一本關(guān)于 vi 的簡(jiǎn)要指南,并 介紹了幾個(gè)類(lèi)似 vi 的程序,其中包括 vim。它可以在以下鏈接中得到:
The Vim Book-vim 項(xiàng)目,一本570頁(yè)的書(shū)籍,包含了(幾乎)所有的 vim 特性。你能在下面鏈接中找到它:
Wikipedia 上關(guān)于 Bill Joy 的文章,vi 的創(chuàng)始人。
Wikipedia 上關(guān)于 Bram Moolenaar 的文章,vim 的作者: