以前にも近い話題でひとつ書いたのですが、
それと重なりながらもちょっとズレるトピックでけっこうハマったので、おもに未来の自分用にまとめておきます。
例題
以下の文字列に対して、最初の apple だけマッチさせるパターンを考えてください。
appleorangeapple
という問題があったとき、「最初の apple だけ」ということは、いわゆる「最短マッチ(非欲張り型)」のパターンを考えることになりますから、Perl だとこんな感じで作れます。
Perl
my $foo = 'appleorangeapple'; say "最短マッチ: $1" if $foo =~ /^(.*?e)/; say "最長マッチ: $1" if $foo =~ /^(.*e)/;
実行。
最短マッチ: apple
最長マッチ: appleorangeapple
パターンの部分だけを取り出すと、こんな感じになります。
/^.*?e/
Vim
次に、Vimで同じことをやりたい場合、通常のVimの正規表現だと、丸括弧などのエスケープ処理がPerlのそれに比べてかなり面倒なため、ここではそうしたVim特有のクセをなるべく排除できるように \vパターンスイッチを使います。
\vパターンスイッチとは何か? ということについて、Vim教科書のマスターピースこと『実践Vim』から説明を抜き出すと、
\vパターンスイッチを使うと、すべての特殊記号に関する規則を正規化できる。(略)
\vパターンにより、Vimの正規表現エンジンの振る舞いはPerl、Python、Rubyにより近いものに切り替わる。それでも違いはあるけれど。
(p244)
とのこと。
ぼくは少し前までは、「Vimの正規表現にはいろいろクセがあるけれど、これを体得してこそ真のVimmerになれるはず……」と思って一つ一つ地道にエスケープしていましたが、最近になって「そろそろラクになってもいいのでは……」と思って\vを使うようになりました。
するとたしかに、大半のケースにおいてはそれでほぼ、Perlで使うのと同様の結果を期待できるのですが、今回とり上げる最短マッチはその例外、つまり上の説明で言うところの「それでも違いはあるけれど。」にあたるようで、Vimで\vパターンスイッチを付けながら同じことをやろうとすると、こんな感じになります。
/\v^.{-}e
先ほどのPerlの場合とパターンの中身だけ並べてみましょう。
^.*?e ^.{-}e
Perlでは「*?」となっていた部分が、Vimだと「{-}」になっています。
ちなみに、最長マッチのほうでは、PerlもVimもこれで行けます。
^.*e
つまりここでの違いは、Vimにおいては「?」を最短マッチの道具として使えない、ということですね。
もう少し具体的に言うと、Vimでは単純に「?」の代わりに何かを使うとか、「?」をエスケープするとかではなく、「*?」を「{-}」で代替するという、なかなか自然には想像のつきづらい規則だったので、把握するまでにけっこうな時間を要しました。
ちなみに、Perlにおける「.+?」はVimだと「.{-1,}」になるようです。
このあたりの情報については、前回の記事でも謝辞とともに紹介しました以下のサイトのまとめが非常にわかりやすかったです。
実際の用途としては、ひとまずVimでは「.{-}」がPerlにおける「.*?」の代わりになる、とだけ覚えておけば大半の状況は乗り越えられそうな気がしますが、とはいえ1年で何回使うかわからないぐらいレアなパターンかもしれないので、忘れてしまってもすぐに思い出せるよう、ここにまとめておきました。
- 作者: Drew Neil,新丈径
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2013/08/29
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (15件) を見る