大家應(yīng)該都已經(jīng)知道 Vim 里使用“/模式”(或“?模式”)進(jìn)行搜索,使用“:s/模式/字符串/標(biāo)志”進(jìn)行替換,其中的“模式”是一個正則表達(dá)式。關(guān)于正則表達(dá)式,不熟悉的話可以邊用邊學(xué),本節(jié)也不打算對 Vim 的正則表達(dá)式作完整的闡述(那可能可以專門寫一本小冊子了),而只拋磚引玉式地給出一些有用的例子加以說明,以及一些實(shí)用技巧。
先說一點(diǎn)點(diǎn)搜索。搜索里最最有用的一個快捷方式是“*”(向下完整匹配光標(biāo)下的單詞)。把光標(biāo)移動到你要搜索的詞(變量名、函數(shù)名等)上,比如“test”,然后按 “*”,Vim 將自動產(chǎn)生一個對“\”(參見“:help /\<”和“:help /\>”)的搜索,也就是說,搜索完整的單詞“test”。不要小看這個技巧,它經(jīng)??梢源蠓鹊靥岣咚阉鞯乃俣?。事實(shí)上,這是 Vim 網(wǎng)站上公布的第 1 號技巧,也是被評價最高的技巧。相似的技巧還有“#”(向上完整匹配光標(biāo)下的單詞)、“g*”(向下部分匹配光標(biāo)下的單詞)等,請自行查看(“:help #”等)。
Vim 在搜索和替換時會對匹配成功的文本進(jìn)行加亮,在已經(jīng)完成搜索和替換任務(wù)后,這種加亮有時反而會妨礙顯示。Vim 專門提供一個命令取消這種加亮(直到用戶再一次使用搜索或替換命令):“:nohlsearch”。建議用戶創(chuàng)建一個鍵盤映射(key mapping)加入到 .vimrc 中,如:
以上命令表示,在正常模式下按 F2 鍵相當(dāng)于輸入“:nohlsearch”后面跟一個回車,即取消搜索加亮顯示。
再看幾個搜索替換的實(shí)用例子。
- 去掉所有的行尾空格:“:%s/\s\+$//”?!?”表示在整個文件范圍內(nèi)進(jìn)行替換,“\s”表示空白字符(空格和制表符),“\+”對前面的字符匹配一次或多次(越多越好),“$”匹配行尾(使用“\$”表示單純的“$”字符);被替換的內(nèi)容為空;由于一行最多只需替換一次,不需要特殊標(biāo)志。這個還是比較簡單的。
- 去掉所有的空白行:“:%s/\(\s*\n\)\+/\r/”。這回多了“\(”、“\)”、“\n”、“\r”和 “*”?!?”代表對前面的字符(此處為“\s”)匹配零次或多次(越多越好;使用“\*”表示單純的“*”字符),“\n”代表換行符,“\r”代表回車符,“\(”和“\)”對表達(dá)式進(jìn)行分組,使其被視作一個不可分割的整體。因此,這個表達(dá)式的完整意義是,把連續(xù)的換行符(包含換行符前面可能有的連續(xù)空白字符)替換成為一個單個的換行符。唯一很特殊的地方是,在模式中使用的是“\n”,而被替換的內(nèi)容中卻不能使用“\n”,而只能使用“\r”。原因是歷史造成的,詳情如果有興趣的話可以查看“:help NL-used-for-Nul”。
- 去掉所有的“//”注釋:“:%s!\ s*//.*!!”。首先可以注意到,這兒分隔符改用了“!”,原因是在模式或字符串部分使用了“/”字符,不換用其他分隔符的話就得在每次使用“/”字符本身時寫成“\/”,上面的命令得寫成“:%s/\s*\/\/.*//”,可讀性較低。命令本身倒是相當(dāng)簡單,用過正則表達(dá)式的人估計都知道“.”匹配表示除換行符之外的任何字符吧。
- 去掉所有的“/* */”注釋:“:%s!\s*/\*\_.\{-}\*/\s*! !g”。這個略有點(diǎn)復(fù)雜了,用到了幾個不太常用的 Vim 正則表達(dá)式特性。“\_.”匹配包含換行在內(nèi)的所有字符;“\{-}”表示前一個字符可出現(xiàn)零次或多次,但在整個正則表達(dá)式可以匹配成功的前提下,匹配的字符數(shù)越少越好;標(biāo)志“g”表示一行里可以匹配和替換多次。替換的結(jié)果是個空格的目的是保證像“int/* space not necessary around comments */main()”這樣的表達(dá)式在替換之后仍然是合法的。
希望上面的這些簡單的例子能夠引起你使用 Vim 的正則表達(dá)式高效完成任務(wù)的興趣。進(jìn)一步的信息可參考“:help regexp”。