Vimscript 基本的正則表達(dá)式

2018-02-24 16:02 更新

Vim是一個(gè)文本編輯器,這意味著大量的Vimscript代碼將專(zhuān)注于處理文本。 Vim對(duì)正則表達(dá)式有著強(qiáng)大的支持,盡管一如既往地也有著一些坑。

把下面的文本打到緩沖區(qū)中:

max = 10

print "Starting"

for i in range(max):
    print "Counter:", i

print "Done"

這個(gè)就是我們將用來(lái)測(cè)試Vimscript的正則支持的文本。它恰好是Python代碼,但不要擔(dān)心你看不懂Python。 它只是一個(gè)例子。

我會(huì)假定你懂得基本的正則表達(dá)式。如果你不懂, 你應(yīng)該暫停閱讀本書(shū)并開(kāi)始閱讀Zed Shaw的Learn Regex the Hard Way。 (譯注:暫無(wú)中文版,也可選擇別的書(shū),或者just Google it) 在你看完后再繼續(xù)。

高亮

在開(kāi)始之前,先花點(diǎn)時(shí)間講講搜索高亮,這樣我們可以讓匹配的內(nèi)容更明顯。

:set hlsearch incsearch

hlsearch讓Vim高亮文件中所有匹配項(xiàng),incsearch則令Vim在你正打著搜索內(nèi)容時(shí)就高亮下一個(gè)匹配項(xiàng)

搜索

移動(dòng)你的光標(biāo)到文件頂部并執(zhí)行下面命令:

/print

當(dāng)你逐字母敲打時(shí),Vim開(kāi)始在第一行高亮它們。當(dāng)你按下回車(chē)來(lái)進(jìn)行搜索時(shí),高亮_所有_的print, 同時(shí)移動(dòng)你的光標(biāo)到下一處匹配。

現(xiàn)在嘗試執(zhí)行下面的命令:

:execute "normal! gg/print\<cr>"

這將移動(dòng)到文件頂部并開(kāi)始搜索print,帶我們到第一處匹配。 用的是我們前一章看過(guò)的:execute "normal! ..."語(yǔ)法。

要到達(dá)文件中的第二處匹配,你僅需在命令的結(jié)尾加一點(diǎn)別的。執(zhí)行這個(gè)命令:

:execute "normal! gg/print\<cr>n"

Vim將移動(dòng)光標(biāo)到緩沖區(qū)中的第二個(gè)print(同時(shí)高亮所有匹配)。

讓我們嘗試從反方向開(kāi)始。執(zhí)行這個(gè)命令:

:execute "normal! G?print\<cr>"

這次我們用G移動(dòng)到文件結(jié)尾并用?來(lái)反向搜索。

所有的搜索命令應(yīng)該已經(jīng)爛熟于心 —— 我們?cè)谧屇懔?xí)慣:execute "normal! ..."慣用法時(shí)已經(jīng)反復(fù)練習(xí)過(guò), 因?yàn)樗屇阍赩imscript代碼中能夠做日常在Vim里做的事。

魔力(Magic)

/?命令能接受正則表達(dá)式,而不僅僅是普通字符。執(zhí)行下面命令:

:execute "normal! gg/for .+ in .+:\<cr>"

Vim抱怨說(shuō)找不到模式!我告訴過(guò)你Vim支持正則搜索,所以為何如此?試試下面命令:

:execute "normal! gg/for .\\+ in .\\+:\<cr>"

這次Vim高亮"for"循環(huán),如我們一開(kāi)始所指望的。在繼續(xù)閱讀之前,花一分鐘來(lái)想想為何如此。 記住execute接受一個(gè)字符串。

答案在此:我們需要這樣寫(xiě)命令的原因有二:

  • 首先,execute接受一個(gè)字符串,在調(diào)用normal!命令時(shí),雙反斜杠將轉(zhuǎn)換成單反斜杠。
  • Vim有四種不同的解析正則表達(dá)式的"模式"! 默認(rèn)模式下需要在+前加上一個(gè)反斜杠來(lái)讓它表示"一或多個(gè)之前的字符"而不是"一個(gè)字面意義上的加號(hào)"。

直接在Vim里執(zhí)行搜索,你很容易就注意到它們的不同,輸入下面的命令并按下回車(chē):

/print .\+

現(xiàn)在你可以看到\+的魔力了。雙反斜杠僅僅在把模式作為字符串傳遞給execute時(shí)才需要。

字面量字符串

正如我們?cè)谧址且徽绿岬降?,Vim允許你使用單引號(hào)來(lái)定義可以直接傳遞字符的字面量字符串。 比如,字符串'a\nb'有四個(gè)字符長(zhǎng)。

我們可以使用字面量字符串來(lái)避免頻繁敲打雙重反斜杠嗎? 先思考這個(gè)問(wèn)題一兩分鐘,畢竟答案恐怕比你所認(rèn)為的要更復(fù)雜一些。

試試執(zhí)行下面的命令(注意這次的單引號(hào)和單反斜杠):

:execute 'normal! gg/for .\+ in .\+:\<cr>'

Vim帶你到文件的頂部卻不再移動(dòng)到第一個(gè)匹配的地方。你猜對(duì)了嗎?

命令之所以不能工作,是因?yàn)槲覀冃枰J街械?code>\<cr>被轉(zhuǎn)義成回車(chē),來(lái)啟動(dòng)搜索。 因?yàn)槲覀冇玫氖亲置媪孔址?,它并不等價(jià)于平常在Vim里鍵入/for .\+ in .\+:\<cr>, 顯然這是無(wú)法工作的。

別怕,方法還是比困難多!不要忘了Vim允許字符串連接,所以可以將命令分割成容易理解的一小段。 執(zhí)行下面的命令:

:execute "normal! gg" . '/for .\+ in .\+:' . "\<cr>"

這種方法可以在傳遞給execute之前把三小段字符串連接起來(lái), 而且我們可以為正則使用字面量字符串并為其他的使用一般的字符串。

更多的魔力(Very Magic)

你可能會(huì)好奇Vimscript的四種不同的正則解析模式和它們跟Python,Perl或Ruby中的正則表達(dá)式有何不同。 你可以閱讀它們的文檔,如果你樂(lè)意。不過(guò)如果你只想找到一種簡(jiǎn)單科學(xué)的解決辦法,請(qǐng)繼續(xù)讀下去。

執(zhí)行下面的命令:

:execute "normal! gg" . '/\vfor .+ in .+:' . "\<cr>"

我們又一次把正則表達(dá)式放在單獨(dú)的字面量字符串里,而這次我們用\v來(lái)引導(dǎo)模式。 這將告訴Vim使用它的"very magic"正則解析模式,而該模式就跟其他語(yǔ)言的非常相似。

如果你以\v開(kāi)始你的所有正則表達(dá)式,你就不用再糾結(jié)Vimscript另外三種瘋狂的正則模式了。

練習(xí)

認(rèn)真閱讀:help magic

閱讀:help pattern-overview來(lái)看看Vim支持的正則類(lèi)型。在看到character classes時(shí)停下來(lái)。

閱讀:help match。嘗試手動(dòng)執(zhí)行幾次:match Error /\v.../。

在你的~/.vimrc文件中加入使用match來(lái)高亮多余的空白為錯(cuò)誤的映射。建議使用<leader>w。

加入另一個(gè)映射來(lái)清除匹配項(xiàng)(比如<leader>W)。

加入一個(gè)normal模式下的會(huì)在進(jìn)行搜索時(shí)自動(dòng)插入\v的映射。 如果你卡在這個(gè)練習(xí)上,不要忘了Vim的映射是非常簡(jiǎn)單的,你只需要告訴它把映射鍵轉(zhuǎn)換成哪些鍵。

在你的~/.vimrc文件中加入hlsearchincsearch選項(xiàng),隨你所欲地設(shè)置它。

閱讀:help nohlsearch。注意這是一個(gè)_命令_并且不是hlsearch的"off mode"。

在你的~/.vimrc文件中加入消除最后一次搜索的匹配項(xiàng)的高亮的映射。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)