天天看點

vim中正規表達式(關于magic)

毋庸多言,在vim中正規表達式得到了十分廣泛的應用。最常用的 / 和 :s 指令中,正規表達式都是不可或缺的。下面對vim中的正規表達式的一些難點進行說明。

關于magic

vim中有個magic的設定。設定方法為:

:set magic             " 設定magic
:set nomagic           " 取消magic
:h magic               " 檢視幫助      

vim畢竟是個編輯器,正規表達式中包含的大量元字元如果原封不動地引用(像perl那樣),勢必會給不懂正規表達式的人造成麻煩,比如 /foo(1) 指令,大多數人都用它來查找foo(1)這個字元串,但如果按照正規表達式來解釋,被查找的對象就成了 foo1 了。

于是,vim就規定,正規表達式的元字元必須用反斜杠進行轉義才行,如上面的例子,如果确實要用正規表達式,就應當寫成 /foo/(1/) 。但是,像 . * 這種極其常用的元字元,都加上反斜杠就太麻煩了。而且,衆口難調,有些人喜歡用正規表達式,有些人不喜歡用……

為了解決這個問題,vim設定了 magic 這個東西。簡單地說, magic就是設定哪些元字元要加反斜杠哪些不用加的。簡單來說:

  • magic (/m):除了 $ . * ^ 之外其他元字元都要加反斜杠。
  • nomagic (/M):除了 $ ^ 之外其他元字元都要加反斜杠。

這個設定也可以在正規表達式中通過 /m /M 開關臨時切換。 /m 後面的正規表達式會按照 magic 處理,/M 後面的正規表達式按照 nomagic 處理,而忽略實際的magic設定。

例如:

//m.*          # 查找任意字元串
//M.*          # 查找字元串 .* (點号後面跟個星号)      

另外還有更強大的 /v 和 /V。

  • /v (即 very magic 之意):任何元字元都不用加反斜杠
  • /V (即 very nomagic 之意):任何元字元都必須加反斜杠

例如:

//v(a.c){3}$   # 查找行尾的abcaccadc
//m(a.c){3}$   # 查找行尾的(abc){3}
//M(a.c){3}$   # 查找行尾的(a.c){3}
//V(a.c){3}$   # 查找任意位置的(a.c){3}$      

預設設定是 magic,vim也推薦大家都使用magic的設定,在有特殊需要時,直接通過 /v/m/M/V 即可。

本文下面使用的元字元都是 magic 模式下的。

量詞

vim的量詞與perl相比一點也不遜色。

vim Perl 意義
* * 0個或多個(比對優先)
/+ + 1個或多個(比對優先)
/? 或 /= ? 0個或1個(比對優先),/?不能在 ? 指令(逆向查找)中使用
/{n,m} {n,m} n個到m個(比對優先)
/{n,} {n,} 最少n個(比對優先)
/{,m} {,m} 最多m個(比對優先)
/{n} {n} 恰好n個
/{-n,m} {n,m}? n個到m個(忽略優先)
/{-} *? 0個或多個(忽略優先)
/{-1,} +? 1個或多個(忽略優先)
/{-,1} ?? 0個或1個(忽略優先)

從上表中可見,vim的忽略優先量詞不像perl的 *? +? ?? 那樣,而是統一使用 /{- 實作的。這大概跟忽略優先量詞不常用有關吧。

環視和固化分組

vim居然還支援環視和固化分組的功能,強大,贊一個

vim中正規表達式(關于magic)

關于環視的解釋請參考Yurii的《精通正規表達式》 一書吧。

vim Perl 意義
/@= (?= 順序環視
/@! (?! 順序否定環視
/@<= (?<= 逆序環視
/@<! (?<! 逆序否定環視
/@> (?> 固化分組
/%(atom/) (?: 非捕獲型括号

和perl稍有不同的是,vim中的環視和固化分組的模式的位置與perl不同。例如,查找緊跟在 foo 之後的 bar,perl将模式寫在環視的括号内,而vim将模式寫在環視的元字元之前。

# Perl的寫法
/(?<=foo)bar/

# vim的寫法
//(foo/)/@<=bar