Posted at

vim の自然な正規表現置換

More than 3 years have passed since last update.

基本的な上にチラ裏感あるけど,

なぜかすぐ忘れるので自分が特に使うところだけメモ.


したいこと

ファイル中の

<http://www.w3.org/2000/01/rdf-schema#hogehoge>

<http://www.w3.org/2000/01/rdf-schema#fugafuga>

rdfs:hogehoge

rdfs:fugafuga

とかに全部置換したい場合がある.


どうする?

以下を実行.

:%s/<http:\/\/www.w3.org\/2000\/01\/rdf-schema#\(.\{-}\)>/rdfs:\1/gc

もしくは

:%s/\v\<http:\/\/www.w3.org\/2000\/01\/rdf-schema#(.{-})\>/rdfs:\1/gc


解説


マッチする文字列を検索

Vim では置換する際に置換条件を省略すると,最後に検索した検索条件を利用できる1

なのでまず / による検索で,ハイライトされる範囲が正しい事を確認する.

メタ文字である / をエスケープしつつ2hogehogeの部分に \(.*\) って書く.

/<http:\/\/www.w3.org\/2000\/01\/rdf-schema#\(.*\)>

この状態でEnter押して,検索できるか確かめる.


デフォルトで最長一致になる罠を回避

実は \(.*\) では最長一致のパターンに引っかかってしまう3

たとえば,以下の文字列だとちゃんとhogehogeがマッチするが,

<http://www.w3.org/2000/01/rdf-schema#hogehoge> ?ptlbl .

以下の文字列だとhogehoge> <nyahonyaho>がマッチしてしまう.

<http://www.w3.org/2000/01/rdf-schema#hogehoge> <nyahonyaho> .

最小マッチさせたい場合は .\{-} を使う.さらに,変数に入れたい場合は同様に()で囲んで(.\{-}\)にする.

/<http:\/\/www.w3.org\/2000\/01\/rdf-schema#\(.\{-}\)>


マッチした文字列を置換

マッチしたら満を持して置換コマンドを実行する.

まず置換条件を省略して:%s//って書く.

続いて,\(.*\)\1に入ってるので,rdfs:\1って書く.

このままだと一行で一回しかマッチしないので/gを最後につける.

一応置換する前に確認したい場合は,cもつける.

:%s//rdfs:\1/gc

検索から置換までを一発で書くと,冒頭のコマンドになる.

\vオプションを付けると(){-}に対するエスケープが不要になって一部すっきりするが,

この場合逆に <>をエスケープしなければならなくなるので,どちらが良いかは好みが分かれると思う.

:%s/\v\<http:\/\/www.w3.org\/2000\/01\/rdf-schema#(.{-})\>/rdfs:\1/gc


コマンド履歴を有効活用しよう

正規表現,便利だけど,よっぽど賢くない限り一発でなんとかなるということは稀で,

多くの人は試行錯誤してマッチする正規表現を探すということになると思う.

なので, q: でコマンド履歴, q/ で検索履歴が開けて,

Ctrl-C でコマンドラインにコピーできる,ということを知っていれば,作業スピードが上がると思う.






  1. ここまで出来る!Vimの(ちょっと高度な)正規表現と検索/置換テクニック - http://qiita.com/m-yamashita/items/5755ca2717c8d5be57e4 



  2. 自環境(macvim)だと,置換したい文字列をクリップボードに入れて,NORMAL モードで / を打った後ペーストすると,エスケープすべき位置にバックスラッシュが補完される. 



  3. vim置換 - Qiita http://qiita.com/waoooon/items/8d982e49692c8145ca4b