vi 技巧和訣竅:令人刮目相看的 10 個超酷命令
在使用vi 編輯器時—無論是初次使用的用戶,還是有經驗的用戶—大多數人往往只掌握核心命令集,這些命令可以執行最常用的功能:導航或保存文件;插入、更新、刪除或搜索數據;退出但不保存修改。
但是,vi 編輯器極其強大,特性和功能非常豐富。即使在多年使用vi 之后,您仍然可能會發現有不知道的新命令。本文討論的命令就屬于不太為人所知的命令,但是它們可以簡化您目前采用的操作方法,讓您的工作方式更高效,或者讓您能夠完成原來不知道可以用vi 完成的操作。
打開和關閉行號
vi 編輯器的許多選項可以控制編輯會話的外觀和感覺。使用 :set 命令修改vi 中的會話設置。按 Escape 鍵進入命令模式之后,可以使用 :set all 命令顯示選項和設置的列表。可以設置的選項之一是 number,它的作用是打開和關閉行號
# Internet host table
#
::1 localhost
127.0.0.1 localhost loghost
192.168.0.6 centos5
192.168.0.10 appserv
192.168.0.11 webserv
192.168.0.12 test
192.168.0.5 solaris10 # Added by DHCP
~
~
~
:set number
這個命令讓vi 在當前編輯的文件中的每個記錄上顯示行號。讓vi 進入命令模式之后,可以輸入 :set number 并按回車來打開行號
2 # Internet host table
3 #
4 ::1 localhost
5 127.0.0.1 localhost loghost
6 192.168.0.6 centos5
7 192.168.0.10 appserv
8 192.168.0.11 webserv
9 192.168.0.12 test
10 192.168.0.5 solaris10 # Added by DHCP
可以使用 :set nonumber 命令關閉行號。還可以使用這個命令和 :set number 命令的簡寫,即 :set nu 和 :set nonu。如果需要快速計算要用vi 函數處理的行數,顯示行號會非常有幫助。當行數很多,可能跨多個屏幕時,行號尤其有用。另外,有時候您知道要處理的行范圍,但是需要查明要在vi 命令中使用的初始和結束行號。如果希望每次進入vi 會話時都顯示行號,那么在主目錄中的.exrc 文件中添加 set number 行。
自動縮進
在用某些編程語言編寫代碼時,縮進是樣式的重要部分,可以確保代碼的可讀性更好。如果需要,可以在vi 編輯器中根據編程語言的樣式設置自動縮進。使用 autoindent 打開或關閉自動縮進.
#
#
for file in /etc/*
do
if [[ -f ${file} ]] ; then
echo "${file} is a file"
~
~
~
~
~
:set autoindent
在此之后,如果在一行的開頭輸入空格或制表符,那么后續的新行將會縮進到相同的位置。在命令模式下,輸入 :set autoindent,然后按回車打開自動縮進。通過設置 shiftwidth 確定縮進級別。例如,:set shiftwidth=4 把每級縮進設置為四個空格。
#
#
for file in /etc/*
do
if [[ -f ${file} ]] ; then
echo "${file} is a file"
elif [[ -d ${file} ]] ; then
echo "${file} is a directory"
fi
done
~
~
:set shiftwidth=4
在命令模式下,可以使用>> 命令讓現有的一行增加一級縮進,使用<< 命令減少一級縮進。在這些命令前面加上一個整數,即可讓多行增加或減少一級縮進。例如,把游標放在清單 4 中第 6 行的開頭,進入命令模式之后,輸入 5>> 就會讓下面五行增加一級縮進。
#
#
for file in /etc/*
do
if [[ -f ${file} ]] ; then
echo "${file} is a file"
elif [[ -d ${file} ]] ; then
echo "${file} is a directory"
fi
done
~
~
可以使用 :set noautoindent 命令關閉自動縮進。還可以使用這個命令和 autoindent 命令的簡寫,即 :set ai 和 :set noai。還可以使用 :set ai sw=4 在一個命令中打開縮進并設置縮進級別。如果希望每次啟動vi 會話時都啟用自動縮進并把縮進級別設置為四個空格,那么在主目錄中的.exrc 文件中添加 set ai sw=4 行。
在搜索時不區分大小寫
如您所知,在 UNIX®中執行搜索時,模式匹配是區分大小寫的。但是,如果希望vi 不區分大小寫,那么可以使用 :set ignorecase 命令。使用 :set noignorecase 恢復區分大小寫。還可以使用簡寫(:set ic 和 :set noic)。如果希望每次進入vi 會話時都啟用不區分大小寫的搜索,那么在主目錄中的.exrc 文件中添加 set ignorecase 行。
復合搜索
在vi 中,可以使用/命令搜索字符串,這需要以字面字符串或正則表達式的形式指定要匹配的模式。例如,要想在文件中搜索單詞 echo,只需進入命令模式,輸入/echo,然后按回車。這個命令會找到清單 6 所示文件的第 3 行的第一個單詞。
2 #
3 echo "Starting"
4 file=${1}
5
6 echo ${file}
7
8 if [[ ${file} = 1 ]] ; then
9 ((file=${file}+1))
10 echo "Adding one gives " \
11 ${file}
12 fi
13 echo "Ending"
14 exit
可以使用簡單的正則表達式指定尋找包含某一單詞而且后面有另一個單詞的行。例如,要想尋找包含字符串 echo、后面有零個或更多字符、之后是字符串 file 的第一行,應該使用/echo.*file。在清單 6 所示的文件中,這個命令會找到第 6 行的第一個單詞。
但是,只有這兩個字符串出現在同一行上,這個命令才認為是匹配的。如果希望搜索出現在另一個模式或字符串后面的某個模式或字符串,不管這兩個模式或字符串是否在同一行上,那么可以指定由分號(;)分隔的兩個搜索命令,從而執行復合搜索。例如,要想搜索出現在字符串{file}+1 后面的字符串 echo,應該使用/{file}+1/;/echo/。在清單 6 所示的文件中,這個命令會找到第 10 行的第一個單詞。復合搜索對于尋找代碼中出現在另一個命令后面的某個命令尤其有用—例如,在設置某個變量之后調用函數的地方。
重放搜索模式
當在文件中搜索要替換的模式時,可以讓vi 把要匹配的任何模式保存在緩沖區中;然后,在執行替換時,可以用緩沖區引用號重放它們。方法是把模式放在 \(和 \)之間,這會指示vi 把模式放在編號的緩沖區(1 到 9)中。在執行替換時,可以用緩沖區引用號 \1 到 \9 引用這些緩沖區。
例如,假設要在清單 7 所示的文件中搜索以單詞 Martin 開頭的行并對每個匹配添加前綴 Mr 和后綴 Wicks,那么進入命令模式,輸入vi 命令 :%s/^\(Martin\)/Mr \1 Wicks/g,然后按回車。
snowboarding and mountain biking. Martin has
worked on UNIX systems for over 15 years. Martin also
worked for many years before that on mainframes.
Martin lives in London.
~
~
~
~
:%s/^\(Martin\)/Mr \1 Wicks/g
下面把這個命令分解開解釋一下:
:%s —指示vi 執行替換。
/—模式分隔符。
^\(Martin\)—尋找以字符串 Martin 開頭的行并把這個字符串保存在緩沖區 1 中。
/—模式分隔符。
Mr \1 Wicks —把找到的字符串替換為字符串 Mr,加上緩沖區 1 中的內容,再加上字符串 Wicks。
/—模式分隔符。
g —全局修改(即修改所有匹配的地方)
在搜索和替換字符串中都可以使用緩沖區引用。
snowboarding and mountain biking. Martin has
worked on UNIX systems for over 15 years. Martin also
worked for many years before that on mainframes.
Mr Martin Wicks lives in London.
~
~
~
~
:%s/^\(Martin\)/Mr \1 Wicks/g
書簽
可以讓vi 在文件中的特定位置放上書簽。方法是按 Escape 鍵,再按 M 鍵,然后輸入另一個表示書簽引用的字母表字符。因此,最多可以有 26 個書簽,分別名為 a 到z。要返回到上一書簽,按 Escape 鍵,再按反撇號(`),然后輸入書簽引用字符。
例如,按 Escape 之后按 M 和 A 鍵,就會把當前游標位置保存在書簽 a 中。在編輯會話中,以后希望返回到這個游標位置時,只需按 Escape,然后輸入 `A。可以使用雙反撇號(``)命令在當前書簽和前一個書簽之間切換。
查找、更新、查找下一個、重復
在vi 編輯器中,最有用的搜索/替換特性之一是查找與某個模式匹配的字符串,更新它,然后繼續搜索下一個匹配的字符串,然后選擇是否以相同方式更新它。這與 Microsoft® Word 中的查找下一個/替換功能很相似。您可能已經知道可以在vi 中搜索字符串模式,方法是進入命令模式,輸入/search_pattern(其中的 search_pattern 是字符串或正則表達式),然后按回車。這樣做就會找到與指定的模式匹配的第一個字符串。在此之后,可以在找到的文本上執行任何操作。例如,按 Escape,再按 C 和 W 鍵,再輸入更多文本,就會把找到的字符串替換為另一個單詞。
要想快速地找到與模式匹配的下一個地方,應該按 Escape,然后按 N 鍵。在找到下一個匹配時,可以使用點號鍵(.)在這個位置重復最近的文本操作,比如前一個示例中使用的修改單詞(cw)操作。然后,可以使用這些鍵繼續尋找其他匹配(n)并選擇重復文本操作(.),操作方式與使用 Word 中的查找下一個/替換功能很相似。
切換大小寫
在vi 中,可以切換游標下的字母字符的大小寫,方法是按 Escape,然后按波浪號鍵(~)。這會在小寫和大寫之間來回切換。按著這個鍵,移動游標經過行中的每個字符,就會切換遇到的每個字母字符的大小寫。可以在波浪號前面輸入一個數字,表示希望改變多少個字母字符的大小寫。
篩選
您可能知道,在vi 中按 Escape,輸入 :!command(其中的 command 是要執行的 UNIX 命令),然后按回車,就可以在 shell 中執行命令。例如,:!pwd 顯示編輯會話當前的工作目錄。
但是,還可以把文件的一部分作為標準輸入發送給 UNIX 命令,并用產生的輸出替換編輯緩沖區中的相同部分。例如,如果希望在vi 會話內對清單 9 所示的整個文件進行排序,可以按 Escape,輸入 :1,$!sort 并按回車,這讓vi 把從第一行到文件末尾($)的所有內容傳遞給 sort 命令,用輸出替換指定的部分。
另外,還可以在 shell 命令前面加上從當前游標位置開始希望操作的行數。方法是按 Escape,然后輸入指定行數的數字,然后輸入兩個驚嘆號(!!),最后輸入 UNIX 命令。
可以使用管道分隔符(|)把 UNIX 命令連接在一起,從而在vi 會話中執行復雜強大的篩選。例如,假設要把當前vi 會話的編輯緩沖區中的文件內容替換為每行的第一個空格分隔的字段,按升序排序并轉換為大寫,那么在按 Escape 之后輸入:
保存部分內容
可以保存當前編輯的文件的部分內容,方法是按 Escape,然后輸入 :start,endw file,其中的 start 是當前文件中要保存的第一行,end 是要保存的最后一行,w表示希望寫到另一個文件中(或者覆蓋現有的文件),file 是指定的部分要保存到的文件。對于最后一行,可以使用$表示文件的末尾。可以在w后面使用兩個大于號(>>)表示希望把內容附加到文件中而不是覆蓋文件。清單 12 中的示例把第 6 到第 9 行(含)附加到文件/tmp/newfile 中。
2 # Internet host table
3 #
4 ::1 localhost
5 127.0.0.1 localhost loghost
6 192.168.0.6 centos5
7 192.168.0.10 appserv
8 192.168.0.11 webserv
9 192.168.0.12 test
10 192.168.0.5 solaris10 # Added by DHCP
~
~
~
:6,9w >> /tmp/newfile
結束語
vi 編輯器是一個極其強大的工具,本文提供了一些技巧和訣竅,希望能夠幫助您更高效地編輯文件。請記住,vi 還有更多不太為人所知的特性。祝工作愉快!