Hack #70: 正規表現でマッチする範囲を制限する
Posted at 2009/09/10ツイート
Vim の正規表現には変わった機能として、マッチングの範囲を制限する機能があります。他の正規表現エンジンではあまり見かけない書き方ですが、使い方さえわかれば非常に便利な機能です。
\zs と \ze
\zs (start の s) と \ze (end の e) を使うことでマッチする範囲を限定することができます。例えば、
/function\s\+\zs\k\+
と検索すると、function に続く単語が検索されます。この際、function の部分はハイライトされません。なぜなら、\zs のある箇所からがマッチ対象になるためです。同様に \ze があった場合はそれ以降の文字列はマッチ対象から外れます。
応用例
実際のところ、普段の検索では特段便利な機能ではありません。ここではこれらの使いどころを紹介します。
置換
:s/function\s\+(\zs.*\ze)//g
この置換ではマッチした対象を削除しますが、実際にマッチする対象を制限しているのでその部分だけ削除されます。よってこの置換では、"function" に続く括弧内の文字列が削除されます。
matchstr()
matchstr() 関数は文字列中のマッチする部分を返します。つまり \zs \ze で範囲を制限すれば好きな部分を取得できるということです。 これを使わなかった場合、matchlist() と後方参照を用いれば同様のことは可能ですが非常に煩雑になります。matchlist() はマッチ対象と括弧でグルーピングされた後方参照をリストで返します。 両者の方法を比較すると、例えば、"function" に続く括弧内の文字列を取得する場合は以下のようにします。
let match = matchstr(targetstr, 'function\s\+(\zs.*\ze)')
let list = matchlist(targetstr, 'function\s+(\(.*\))')
let match = empty(list) ? ''
: list[1]
split()
split() 関数は文字列を正規表現がマッチする箇所で分割してリストにして返します。後方参照などは使えないので \zs \ze が威力を発揮します。 また、通常は区切る対象(正規表現がマッチした部分)は分割する際に消えてしまいますが、マッチ対象を調整することでこれも回避できます。 例えば、全ての文字にマッチさせつつ対象が空になるようにすれば、文字単位で分割することもできます。
let chars = split('こんにちは!', '.\zs') " chars == ['こ', 'ん', 'に', 'ち', 'は', '!']
thinca
もどる
blog comments powered by Disqus