Vim是一個文本編輯器,這意味著大量的Vimscript代碼將專注于處理文本。 Vim對正則表達式有著強大的支持,盡管一如既往地也有著一些坑。
把下面的文本打到緩沖區中:
~~~
max = 10
print "Starting"
for i in range(max):
print "Counter:", i
print "Done"
~~~
這個就是我們將用來測試Vimscript的正則支持的文本。它恰好是Python代碼,但不要擔心你看不懂Python。 它只是一個例子。
我會假定你懂得基本的正則表達式。如果你不懂, 你應該暫停閱讀本書并開始閱讀Zed Shaw的[Learn Regex the Hard Way](http://regex.learncodethehardway.org/)。 (譯注:暫無中文版,也可選擇別的書,或者just Google it) 在你看完后再繼續。
## 高亮
在開始之前,先花點時間講講搜索高亮,這樣我們可以讓匹配的內容更明顯。
~~~
:set hlsearch incsearch
~~~
`hlsearch`讓Vim高亮文件中所有匹配項,`incsearch`則令Vim在你正打著搜索內容時就高亮下一個匹配項
## 搜索
移動你的光標到文件頂部并執行下面命令:
~~~
/print
~~~
當你逐字母敲打時,Vim開始在第一行高亮它們。當你按下回車來進行搜索時,高亮_所有_的`print`, 同時移動你的光標到下一處匹配。
現在嘗試執行下面的命令:
~~~
:execute "normal! gg/print\<cr>"
~~~
這將移動到文件頂部并開始搜索`print`,帶我們到第一處匹配。 用的是我們前一章看過的`:execute "normal! ..."`語法。
要到達文件中的第二處匹配,你僅需在命令的結尾加一點別的。執行這個命令:
~~~
:execute "normal! gg/print\<cr>n"
~~~
Vim將移動光標到緩沖區中的第二個`print`(同時高亮所有匹配)。
讓我們嘗試從反方向開始。執行這個命令:
~~~
:execute "normal! G?print\<cr>"
~~~
這次我們用`G`移動到文件結尾并用`?`來反向搜索。
所有的搜索命令應該已經爛熟于心 —— 我們在讓你習慣`:execute "normal! ..."`慣用法時已經反復練習過, 因為它讓你在Vimscript代碼中能夠做日常在Vim里做的事。
## 魔力(Magic)
`/`和`?`命令能接受正則表達式,而不僅僅是普通字符。執行下面命令:
~~~
:execute "normal! gg/for .+ in .+:\<cr>"
~~~
Vim抱怨說找不到模式!我告訴過你Vim支持正則搜索,所以為何如此?試試下面命令:
~~~
:execute "normal! gg/for .\\+ in .\\+:\<cr>"
~~~
這次Vim高亮"for"循環,如我們一開始所指望的。在繼續閱讀之前,花一分鐘來想想為何如此。 記住`execute`接受一個字符串。
答案在此:我們需要這樣寫命令的原因有二:
* 首先,`execute`接受一個字符串,在調用`normal!`命令時,雙反斜杠將轉換成單反斜杠。
* Vim有四種不同的解析正則表達式的"模式"! 默認模式下需要在`+`前加上一個反斜杠來讓它表示"一或多個之前的字符"而不是"一個字面意義上的加號"。
直接在Vim里執行搜索,你很容易就注意到它們的不同,輸入下面的命令并按下回車:
~~~
/print .\+
~~~
現在你可以看到`\+`的魔力了。雙反斜杠僅僅在把模式作為字符串傳遞給`execute`時才需要。
## 字面量字符串
正如我們在字符串那一章提到的,Vim允許你使用單引號來定義可以直接傳遞字符的字面量字符串。 比如,字符串`'a\nb'`有四個字符長。
我們可以使用字面量字符串來避免頻繁敲打雙重反斜杠嗎? 先思考這個問題一兩分鐘,畢竟答案恐怕比你所認為的要更復雜一些。
試試執行下面的命令(注意這次的單引號和單反斜杠):
~~~
:execute 'normal! gg/for .\+ in .\+:\<cr>'
~~~
Vim帶你到文件的頂部卻不再移動到第一個匹配的地方。你猜對了嗎?
命令之所以不能工作,是因為我們需要模式中的`\<cr>`被轉義成回車,來啟動搜索。 因為我們用的是字面量字符串,它并不等價于平常在Vim里鍵入`/for .\+ in .\+:\<cr>`, 顯然這是無法工作的。
別怕,方法還是比困難多!不要忘了Vim允許字符串連接,所以可以將命令分割成容易理解的一小段。 執行下面的命令:
~~~
:execute "normal! gg" . '/for .\+ in .\+:' . "\<cr>"
~~~
這種方法可以在傳遞給`execute`之前把三小段字符串連接起來, 而且我們可以為正則使用字面量字符串并為其他的使用一般的字符串。
## 更多的魔力(Very Magic)
你可能會好奇Vimscript的四種不同的正則解析模式和它們跟Python,Perl或Ruby中的正則表達式有何不同。 你可以閱讀它們的文檔,如果你樂意。不過如果你只想找到一種簡單科學的解決辦法,請繼續讀下去。
執行下面的命令:
~~~
:execute "normal! gg" . '/\vfor .+ in .+:' . "\<cr>"
~~~
我們又一次把正則表達式放在單獨的字面量字符串里,而這次我們用`\v`來引導模式。 這將告訴Vim使用它的"very magic"正則解析模式,而該模式就跟其他語言的非常相似。
如果你以`\v`開始你的所有正則表達式,你就不用再糾結Vimscript另外三種瘋狂的正則模式了。
## 練習
認真閱讀`:help magic`。
閱讀`:help pattern-overview`來看看Vim支持的正則類型。在看到character classes時停下來。
閱讀`:help match`。嘗試手動執行幾次`:match Error /\v.../`。
在你的`~/.vimrc`文件中加入使用`match`來高亮多余的空白為錯誤的映射。建議使用`<leader>w`。
加入另一個映射來清除匹配項(比如`<leader>W`)。
加入一個normal模式下的會在進行搜索時自動插入`\v`的映射。 如果你卡在這個練習上,不要忘了Vim的映射是非常簡單的,你只需要告訴它把映射鍵轉換成哪些鍵。
在你的`~/.vimrc`文件中加入`hlsearch`和`incsearch`選項,隨你所欲地設置它。
閱讀`:help nohlsearch`。注意這是一個_命令_并且_不是_`hlsearch`的"off mode"。
在你的`~/.vimrc`文件中加入消除最后一次搜索的匹配項的高亮的映射。
- 前言
- 鳴謝
- 預備知識
- 打印信息
- 設置選項
- 基本映射
- 模式映射
- 精確映射
- Leaders
- 編輯你的Vimrc文件
- Abbreviations
- 更多的Mappings
- 鍛煉你的手指
- 本地緩沖區的選項設置和映射
- 自動命令
- 本地緩沖區縮寫
- 自動命令組
- Operator-Pending映射
- 更多Operator-Pending映射
- 狀態條
- 負責任的編碼
- 變量
- 變量作用域
- 條件語句
- 比較
- 函數
- 函數參數
- 數字
- 字符串
- 字符串函數
- Execute命令
- Normal命令
- 執行normal!
- 基本的正則表達式
- 實例研究:Grep 運算符(Operator),第一部分
- 實例研究:Grep運算符(Operator),第二部分
- 實例研究:Grep運算符(Operator),第三部分
- 列表
- 循環
- 字典
- 切換
- 函數式編程
- 路徑
- 創建一個完整的插件
- 舊社會下的插件配置方式
- 新希望:用Pathogen配置插件
- 檢測文件類型
- 基本語法高亮
- 高級語法高亮
- 更高級的語法高亮
- 基本折疊
- 高級折疊
- 段移動原理
- Potion段移動
- 外部命令
- 自動加載
- 文檔
- 發布
- 還剩下什么?