Vimでパターン検索するなら知っておいたほうがいいこと
この記事はVim Advent Calendar 2012の166日目の記事です。
165日目はaueweさんによる.vimrcに書くべきでないVimの設定項目でした。
Vimに限りませんが、テキストエディタを使う際にテキスト検索はよく使うと思います。 ある程度慣れた人だと正規表現を用いたパターン検索を使うようになります。 もちろん、Vimにも正規表現を用いたパターン検索を行う機能は備わっています。 しかし、お世辞にもVimのデフォルト設定ではパターン検索は書きやすいとは言えません。 特に、他の正規表現方言に慣れている人は、Vimの正規表現の書き方の違いに戸惑うと思います。 本記事では、Vimでパターン検索するなら知っておいたほうがいいこと+ Vimのパターン検索に使えるメタ文字をご紹介します。
パターンって何?という方は:help usr_27.txt
を一読することをおすすめします。
一般的な正規表現について詳しく知りたい方は、ウェブや書籍などで一度しっかり勉強することをおすすめします。
ちょっと難しいですが、おすすめの書籍はサイドバーに載せてますのでご参考までに。
Vimでのパターン検索
Vimで正規表現を用いたパターンは、検索コマンド/
での検索、:subsutitute
コマンド
のパターン部分、:global
、:vglobal
コマンドのパターン部分などで使うことができます。
ただ、オプションによってパターンで扱うメタ文字(正規表現として扱う特殊な文字、文字列)の指定の仕方に違いがあります。
オプション名はmagic
で、現在のオプション値を確認するためには以下のようにコマンドを実行します。
:set magic?
デフォルトはmagic
なので、おそらくmagic
と表示されるはずです。
試しに検索コマンドでパターン検索をしてみましょう
以下は、0文字以上の任意の文字列にマッチするパターンです。
/.*
普段は.*だけでパターンを書くことはないと思いますが、一般的な正規表現ですね。
次は、fooかbarにマッチするパターンを入力してみましょう。
/\(foo\|bar\)
検索は出来ましたが、何か\
でたくさん前置してますね。
そうなんです。Vimのデフォルトのmagic
オプションでは、一部の特殊文字は、
\
で前置しないとメタ文字として扱われません。
厄介なのが、メタ文字として扱うために前置する必要がある文字と、 前置が不要な文字が混在しているのです。
例えば、magic
の場合、.
,*
,^
,$
は\
で前置しなくてもメタ文字として扱われますが、
(
,)
,|
,+
,?
は\
で前置しないとメタ文字として扱われません。
正直慣れていても、誤爆する事が多々あります。
要は慣れてないってことですねorz
特に+
は鬼門。。。
very magic
を使う
上記問題は、very magic
を使うことで解消出来ます。
vim Hacksでも紹介があったのでご存じの方も多いと思います。
この機能を使うと、正規表現に使うすべての特殊文字が\
で前置せずに使えるようになります。
ただ残念ながらこの機能、set verymagic
のようにオプションとして設定出来ません。
very magic
を有効にするには、パターンを入力するところで\v
と入力します。
すると\v
以降がvery magic
として扱われます。
例えば検索コマンドでは以下の様に入力します。
/\v
very magic
を有効にした状態でfooかbarにマッチする文字列を検索してみましょう。
/\v(foo|bar)
これで、パターン検索する際に(
も|
も)
も\
で前置する必要はなくなりました。
他にも、+
,?
,{
など、よく使う正規表現のメタ文字が\
での前置なしで使えるようになります。
私はパターン検索を常用しており、毎回\v
と入力するのが嫌なので、以下のようにキーマップを設定しています。
nnoremap / /\v
これで大分Vimでのパターン検索がしやすくなりました。
Vimのパターン検索に使えるメタ文字
very magic
で、パターン検索でのメタ文字の入力が楽になりました。
ただ、Vimのパターンはちょっとした方言があるので、よく使うメタ文字をまとめておきたいと思います。
わかりやすさのため使っている人が多いと思われるPerlの正規表現方言との比較を載せます。
簡単な比較は:help perl-patterns
に載っています。
ここでまとめるVimのメタ文字はすべてvery magic
の指定を前提としており\
で前置していませんのでご注意ください。
また、全てを網羅しているわけではないので、詳細が知りたい方は:help pattern-overview
で調べるといいです。
ただし、helpにはmagic
とnomagic
しか載ってません。といってもvery magic
は基本的にはmagic
で
前置されている\
をとるだけなのでhelpを見て困ることはないと思います。
Perlのメタ文字 | Vimのメタ文字 | 説明 | 備考 |
---|---|---|---|
. |
同じ | 任意の1文字 | |
* |
同じ | 直前のアトムの繰り返し(0回以上) | 最長マッチ |
+ |
同じ | 直前のアトムの繰り返し(1回以上) | 最長マッチ |
? |
同じ(= も同じ) |
直前のアトム(0回、または1回) | 最長マッチ |
{n,m} |
同じ | 直前のアトムの繰り返し(n回以上m回以下) | 最長マッチ |
^ |
同じ | 先頭にマッチ | |
$ |
同じ | 末尾にマッチ | |
(...) |
同じ | グループ化してアトムにする | |
| |
同じ | 選択の区切り | |
[...] |
同じ | [...] 内の任意の1文字にマッチ |
|
\w |
同じ | 単語を構成する文字([0-9A-Za-z_] ) |
|
\W |
同じ | 単語を構成する文字以外([\^0-9A-Za-z_] ) |
|
\d |
同じ | 数字([0-9] ) |
|
\D |
同じ | 数字以外([\^0-9] ) |
|
\s |
同じ | 空白文字(微妙に違う。後述) | |
\S |
同じ | 空白文字以外(微妙に違う。後述) | |
*? |
{-} |
直前のアトムの繰り返し(0回以上) | 最短マッチ |
+? |
{-1,} |
直前のアトムの繰り返し(1回以上) | 最短マッチ |
?? |
{-0,1} |
直前のアトム(0回、または1回) | 最短マッチ |
{n,m}? |
{-n,m} |
直前のアトムの繰り返し(n回以上m回以下) | 最短マッチ |
\b |
< or > |
単語の境界にマッチ(< は単語先頭、> は単語末尾) |
|
(?=atom) |
atom@= |
幅ゼロの肯定先読み | |
(?!atom) |
atom@! |
幅ゼロの否定先読み | |
(?<=atom) |
atom@<= |
幅ゼロの肯定後読み | |
(?<!atom) |
atom@<! |
幅ゼロの否定後読み | |
(?>atom) |
atom@> |
幅ゼロの否定後読み | |
(?:...) |
%(...) |
グループ化して部分正規表現としてカウントしない |
その他Vim特有の便利なメタ文字
Vim特有で便利なメタ文字を紹介します。
メタ文字 | 説明 | 備考 |
---|---|---|
\zs |
どこにでもマッチしてマッチの開始地点を設定する | foo\zsbar とすればfoobarのbarの部分にマッチします |
\ze |
どこにでもマッチしてマッチの終了地点を設定する | foo\zebar とすればfoobarのfooの部分にマッチします |
%[...] |
任意にマッチするアトム列 | r%[ead] とすれば'r','re','rea','read'にマッチします |
PerlとVimで正規表現の意味が異なる主なメタ文字
PerlとVimで意味が異なる主なメタ文字を紹介します。
他にもあるので、使用する際は、:help \x
などで調べてから
使用することをおすすめします。
メタ文字 | Perl | Vim |
---|---|---|
\s |
スペース、タブ(\t )、改行文字(\n )、復帰文字(\r )、フォームフィード(\f ) |
スペース、タブ(\t ) |
\S |
上記以外 | 上記以外 |
\b |
単語境界 | <BS> にマッチ |
\B |
単語境界以外 | なし |
\A |
文字列の先頭 | 英字以外 |
\Z |
文字列の最後 | Unicodeの合成文字は無視 |
very nomagic
を使う
very magic
でメタ文字を入力しやすくなりましたが、\
で前置が必要な文字がいっぱいあって、
メタ文字じゃなくてその文字自体を検索したい場合に困るという方は、
very nomagic
を使うと便利です。
very nomagic
はパターンを指定するところで、\V
と入力するとそれ以降の文字で
すべての特殊文字は\
で前置が必須になります。
つまり\
を検索したい場合だけ\\
とすればよく、他の文字は\
で前置せずに
検索することが出来るようになります。
例えば、very magic
で入力していて、ここからは普通にテキスト検索したいと思ったら途中で
\V
でvery nomagic
に切り替えることができます。
以下の様に入力します。
/\v(foo|bar)\V(foo|bar)
これは、fooかbarにマッチする文字列の後に(foo|bar)という文字列を検索という意味になります。
ちなみにデフォルトのmagic
は\m
、他にもnomagic
の指定は\M
と指定することで切り替えられます。
\v
,\V
,\m
,\M
はやろうと思えば、パターン内で何度も切り替えられるので便利です。
エスケープが必要な文字
very magic
だとすべての特殊文字が前置不要になるためその特殊文字自体に
マッチさせたい場合は\
でエスケープが必要になります。
また、very magic
、magic
、nomagic
、very nomagic
と、それぞれエスケープが
必要な文字が異なります。
ここでは、very magic
、magic
、nomagic
、very nomagic
のそれぞれでエスケープが必要な特殊文字(つまりその文字単体でメタ文字として扱われる文字)をまとめます。
very magic
の場合
\
.
*
+
?
=
{
^
$
(
)
|
[
&
@
~
/
(検索コマンド/
で検索する場合、/
でパターンを囲う場合)
特に、=
,&
,@
,~
は、Perlの正規表現方言ではメタ文字ではないのでハマりポイントです。
magic
の場合
\
.
*
^
$
[
~
/
(検索コマンド/
で検索する場合、/
でパターンを囲う場合)
nomagic
の場合
\
^
$
/
(検索コマンド/
で検索する場合、/
でパターンを囲う場合)
very nomagic
の場合
\
/
(検索コマンド/
で検索する場合、/
でパターンを囲う場合)
おまけ
関連オプション
パターン検索に関連するオプションを紹介します。
" 大文字と小文字を無視する set ignorecase " 大文字と小文字を無視しない set noignorecase " 検索パターンが大文字を含んでいたら'ignorecase'を上書きする。('ignorecase'オンのときのみ使われる) set smartcase " 'ignorecase'を上書きしない set nosmartcase " メタ文字として扱う文字を`magic`で指定(`.`,`*`,`$`,`^`,`[`などを`\`で前置なしでメタ文字として扱う) set magic " メタ文字として扱う文字を`nomagic`で指定(`$`,`^`などを`\ `で前置なしでメタ文字として扱う) set nomagic
Perlのplugin使う
Perl/Ruby方言の正規表現で検索、置換などができる eregex.vimというplugin があります。
ただ、eregex.vimはインクリメンタルサーチができません。 何より、突然素のVimを使う必要に迫られた際や、 急に思い立ってVim scriptを書きたいと思った時にも、 Vimの正規表現が使えなくて困るかもしれません。
なので、本記事ではインクリメントサーチが不要な方で、 どうしてもPerl/Ruby方言の正規表現じゃなきゃやだ! という方以外にはおすすめしません。
ちなみに私はPerl使い(というほどたいしたものでもありませんが。。。)なので、
しばらく、eregex.vimを使っていた時期がありました。
ただ、very magic
を知ってからは、Vimの正規表現もそんなに不便なく使えることがわかったので、
今はVimのパターン検索を使っています。
Vimのパターン検索で参考になるhelp
Vimのパターン検索は以下のhelpを参照するといいです。 本記事で書いたことはほとんどhelpに書かれていることです。
:help usr_27.txt :help pattern.txt
まとめ
以上が、Vimでパターン検索する際に知っておくと便利なことでした。
正直ほとんどhelpに載っている話だったり、他の方が書かれた記事と変わらなかったりしますが、自分の整理のために書いてみました。
ちょっととっつきにくいだけでVimの正規表現は普通に使えるのでちょこちょこ使ってVimの正規表現に慣れていくことをおすすめします。
もしパターン検索について、こんなことも載せて欲しいとか、これも載せたほうがいいとかあれば、コメントやTwitterなどでご指摘いただけるとうれしいです。
あと、Vimのパターン検索に限りませんが、Vimレベルが上がるのでvimrc読書会に参加することをおすすめします。毎週土曜日23時からやってます。 次回(5/18)は大御所kanaさんのvimrcを読む予定です。すごいことになりそう。。。
それではVim Advent Calendar 2012の166日目を終わります。
明日のVim Advent Calendar 2012はyonchuさんです。