Hack #75: 正規表現で先読み/後読みを使用する
Posted at 2009/09/20ツイート
Hack #70 で、正規表現においてマッチする範囲を制限する方法を紹介しましたが、他の正規表現エンジンで同じようなことをしたい場合、肯定先読みや否定先読みと言った機能が使われます。 そして当然、Vim にも肯定先読みや否定先読みの機能は備わっています。
肯定先読み/否定先読み/肯定後読み/否定後読み
先読み、後読みとはすなわち、特定のパターンが対象のパターンの後ろに来る(先読み)、もしくは前に来る(後読み)ことを条件付けることです。否定の場合は逆に来ないことを条件付けます。
肯定の場合は単に続けて正規表現を構成した場合でもマッチする個所は同じですが、マッチする対象が異なります。先読み、後読みの部分はあくまで条件なのでマッチ対象には含まれません。
Vim では以下のパターンを置くことで直前の文字、もしくはグループを先読み、後読みに指定します。
肯定先読み | \@= |
---|---|
否定先読み | \@! |
肯定後読み | \@<= |
否定後読み | \@<! |
例えば、
\w\+\%(()\)\@=
とすると直後に "()" が来る単語にマッチします。また、
\%(function\s\+\)\@<!\w\+
とすると直前に "function" と空白文字が来ない単語にマッチします。
\zs \ze との関係
\zs や \ze は肯定先読み/肯定後読みの省略形と考える事ができます。すなわち、
foo\zsbar\ze\baz
と
\%(foo\)\@<=bar\%(baz\)\@=
は同義になります。ただし、読み易さや処理速度を考えると可能ならば前者を使う方が良いでしょう。
Perl との比較
Vim の先読み/後読みは他の正規表現エンジンとは少し違う書き方をします。 例えば Perl の正規表現エンジンでは () でグループを作り、グループに対して先読み、後読みの指定をします。 対して Vim では、直前の文字、もしくはグループに対して先読み、後読みを指示する指定子があります。 Perl の書き方に慣れた人にとっては最初はわかりづらいかもしれませんが、慣れれば大した違いはありません。
Vim | Perl | |
---|---|---|
肯定先読み | \%(pattern\)\@= | (?=pattern) |
否定先読み | \%(pattern\)\@! | (?!pattern) |
肯定後読み | \%(pattern\)\@<= | (?<=pattern) |
否定後読み | \%(pattern\)\@<! | (?<!pattern) |
また、Vim の後読みは Perl と違い可変長パターンも扱えます。ただし後読みは少々重いので処理速度には注意が必要です。
thincaもどる
blog comments powered by Disqus