特別企画
使いこなせば検索・置換が捗る! 「EmEditor」で正規表現を身に着けよう
基本から無理せず少しずつステップアップし、目指せ脱初心者
(2015/12/25 20:21)
テキストエディターを使いこなすためにぜひとも覚えてほしいものの一つに“正規表現(regular expression)”がある。正規表現を利用すれば、“文字列のパターン”を記述して、一般の機能では実現できない高度な検索・置換を行うことができる。しかし、正規表現は一見すると複雑で、とっつきにくいと感じているユーザーも少なくないのではないだろうか。
そこで本稿では、正規表現エンジンとして“Onigmo”が選べるようになった「EmEditor」v15.7を利用して、正規表現の基本的な使い方を紹介する。
メタ文字さえ使わなければ、正規表現なんて一般の検索と同じ!
正規表現には、特別な意味を持つ特殊文字がある。これを“メタ文字(メタキャラクター)”と呼ぶ。よく使われるメタ文字には以下のようなものがある。
$ ( ) * + . [ ] ? \ ^ { } |
それぞれのメタ文字の意味についてはあとで説明するので、まだ覚える必要はない。このようなものがあると把握できていればそれで十分だ。
実は、これらメタ文字さえ使わなければ正規表現を利用した検索であっても、一般の検索と結果に変わりはない。
「EmEditor」の場合、検索ダイアログで[正規表現を使用する]オプションを有効にしていれば正規表現を利用した検索が可能となるが、その場合でも、メタ文字さえ使わなければ一般の検索機能と同様に扱うことができるのがわかる。正規表現を過度に恐れず、まずはオプションを有効にしてみるところから始めてみよう。
なお、正規表現検索を有効にしていると、メタ文字がマッチ(一致。検索にヒットすること)しない。たとえば、検索ボックスに“$”と入力して検索を行っても、“$”にヒットすることはない。
この場合は、メタ文字として利用しないことを明示的に示すために“\(バックスラッシュ)”を付与する(これをエスケープと呼ぶ)。たとえば、“$”を検索したい場合は“\$”とする。“\”という文字を検索対象としたい場合は“\\”とすればよい。特殊な記号がマッチしない場合や、意図した通りに正規表現がマッチしてくれない場合は、まずエスケープ忘れを疑ってみよう。
“なにか1文字”を表す記号“.(ピリオド)”を覚えよう!
それでは、正規表現のメタ文字を一つ一つ会得していくことにしよう。まず覚えてほしいのが、“なにか1文字”を表す記号“.(ピリオド)”だ。
たとえば、“「.」”というパターンは“括弧で囲まれたなにか1文字”を表す。例として、小説から“「」(引用符)”で囲まれたセリフを抜き出すことを考えてみよう。
- “「.」”:“「あ」”“「!」”といった1文字だけのセリフ
- “「..」”:2文字のセリフ
- “「...」”:3文字のセリフ
- “「あ..」”:あから始める3文字のセリフ
“.”は正規表現でもっとも多用するメタ文字の一つなので、ぜひマスターしてほしい。
1文字だけじゃ困る……繰り返しを使いこなそう
しかし、あらかじめ決まった文字数のセリフばかり検索できても、使い道はあまりないかもしれない。たとえば、小説ではセリフの長さはさまざまであることが普通だからだ。では、“何文字でもいい”場合はどのように表現すればよいのだろうか。
そういうときのために、正規表現では繰り返し記法(量指定子)が用意されている。
- “あ{n}”:n個ちょうどの“あ”の連続にマッチ
つまり、先ほどの2文字のセリフを表すパターンは、“「.{2}」”と書ける。このパターンは「ふん」や「ええ」などの2文字のセリフにマッチする。3文字のセリフならば、“「.{3}」”だ。
また、正規表現の繰り返し記法では最小量と最大量を指定することもできる。
- “あ{min,}”:min個以上連続する“あ”にマッチ
- “あ{min, max}”:min個以上max個以下の連続する“あ”にマッチ
- “あ{,max}”:最大max個の連続する“あ”にマッチ
と表現する。たとえば、2文字以上のセリフを抜き出したい場合は、
「.{2,}」
と記述すればよいだろう。
マッチするセリフの文字数に制限を設けない場合は“1文字以上の文字”を指定すればよいので、
「.{1,}」
というパターンでよい。
なお、繰り返し記法のうち、以下の3つは利用頻度が高いので、特別なメタ文字が割り当てられている。
- “あ{0,1}” → “あ?”:0個または1個の“あ”にマッチ
- “あ{0,}” → “あ*”:0個以上連続する“あ”にマッチ
- “あ{1,}” → “あ+”:1個以上連続する“あ”にマッチ
この3つのメタ文字は繰り返し記法“{}”で代用できるため、最初は覚えなくてもよい。しかし、知っていればより正規表現らしいスマートな記述が可能となる。たとえば、先ほどの“「.{1,}」”というパターンは、
「.+」
と書ける。“{}”記法より簡単で読みやすいため、“{}”記法に慣れてきたらチャレンジしてみよう。
ちなみに、“0個の文字”という表現は少しわかりにくいかもしれないが、“冬景色”でも“冬の景色”のどちらにマッチしてもいい場合に使う(“冬の?景色”)。必要に迫られれば自然と覚えるので、わからない場合は読み飛ばしてもよい。
【コラム】欲張りなマッチと控えめなマッチ
“「.+」”というパターンで検索した場合に、セリフを閉じる“」”でマッチが終了せず、思った以上に長いテキストが検索にヒットする場合がある。
これは、最初に見つかった“」”で探索を終えず、なるべく次の“」”を探そうとする“欲張りなマッチ”が働いているためだ。これを防ぐには、
“「.+?」”
と“?”を加えて、“控えめなマッチ”(最初に“」”が見つかった時点で検索をやめる)を行うように指定すればよい。
なお、これは“+”だけでなく、“{}”による繰り返し記法や“*”でも同様に利用できる。
- “あ{0,}?” → “あ*?”
- “あ{1,}?” → “あ+?”
また、
「[^」]+」
と明示的に集合(後述)を用いて“」を除く文字集合にマッチせよ”と書く方法もある。
マッチする文字の種類を絞りたい――選言と集合
さて、ここからは少し例をかえ“郵便番号をマッチさせる”ケースを考えてみたい。たとえば、CSV形式で住所データをもらったが、郵便番号の欄に不備がないかどうかをチェックしなければならないといったケースだ。
郵便番号の形式は、“000-0000”だ。なので、ここまでで習ったメタ文字を利用すると、
...-....
や、
.{3}-.{4}
でマッチさせられるとわかる。しかし、“.”は半角数字以外の文字にもマッチしてしまうため、
791-8013 あいう-えおかきく
のような誤った表記を見逃してしまうかもしれない。“なにか1文字、ただし半角数字のみ”という条件を表すにはどうすればよいだろうか。
正規表現では“[]”を利用して文字列の集合を表現することができるので、それを利用すればよい。たとえば、半角数字は
[0123456789]
と表せる。つまり、これを“.”の代わりに利用して
[0123456789]{3}-[0123456789]{4}
と記述すればよい。
この“[0123456789]”は、短縮して
[0-9]
と表すことも可能。なので、郵便番号は
[0-9]{3}-[0-9]{4}
と表せる。なお、短縮表示にする場合、文字コードの小さい文字から大きい文字までを指定する必要がある。そのため、[1-0]という表記は不正となるので注意しよう。
そのほかにも、
- [A-z]:アルファベット
- [ぁ-ん]:ひらがな
- [亜-熙]:漢字(Shift_JISやEUCの場合。ただし、「EmEditor」は内部的にUnicodeが使用されているため、正規検索エンジンに“Boost.Regex”を利用した場合は“[\x{3400}-\x{9fff}\x{f900}-\x{fa2d}]”といった表記にする必要がある)
などの集合を知っておくと便利だ。
しかし、いちいち覚えておくのは面倒かもしれない。なので、数字に関してはメタ文字“\”を利用した記法が用意されている。
- \d:10進数字
これを利用すれば、先ほどの郵便番号のパターンは
\d{3}-\d{4}
と表せる。ぐっと正規表現っぽくなった感じがするだろう(「EmEditor」では、正規検索エンジンに“Boost.Regex”を利用すると全角数字にもマッチしてしまうことに注意したい。“Onigmo”ならばマッチしない)。しかし、覚えきれない場合は、冗長だがより汎用的な表現だけ覚えていけば十分だ。必要に迫られれば自然にこのような短縮表現は身につく。
なお、できればもう一つ覚えておいてほしいものに、“^(キャレット)”がある。
“^”は“行の先頭”を示す(後述)が、集合で否定を表すのにも利用する。たとえば、“[^ア]”は“アを除くすべての文字”を表す。“[^アイウエオ]”は“アイウエオを除くすべての文字”を表す。
【コラム】その他に覚えておくと便利な文字集合
数字の集合以外にも、以下の集合を覚えておくと役に立つ。
- \w:単語構成文字(単語を構成する文字。英数字+“_”など)
- \s:空白文字(スペースやタブ、改行など)
- \t:タブ
- \n:改行
ちなみに、大文字にすれば否定(~ではない文字、補集合)を表すことができる。
- \D:10進数字ではない文字
- \W:単語構成文字(単語を構成する文字。英数字+“_”など)ではない文字
- \S:空白文字(スペースやタブ、改行など)ではない文字
また、v15.7.0で利用できるようになった“Onigmo”を正規表現にすれば、以下のような記法が利用できる。
- \p{Num}:数字
- \p{Alpha}:アルファベット
- \p{Hiragana}:ひらがな
- \p{Katakana}:カナカナ
- \p{Han}:漢字
さて、これだけ覚えるだけでもかなりのことができるようになるが、もう一つ覚えておいて損がないのは“どっちでもいい”ことを表す“|”だ。
たとえば、“Windows”と“windows”の両方で検索したい場合、これまで覚えたことだけで書くならば、集合を利用してこのようなパターンになるだろう。
[Ww]indows
しかし、これは“選言(または)”を利用してこのように書くこともできる。
(W|w)indows
カッコでグルーピングし、メタ文字“|”でマッチさせたい文字を複数つないでいけばよい。この記法のよいところは、以下のパターンが記述できる点だ。
Theat(re|er)
このパターンは、“Theater(劇場:アメリカ綴り)”と“Theatre(劇場:イギリス綴り)”の両方をヒットさせることができる。また、日ごろよく使いそうな例としては、画像の拡張子を探したいというケースがありそうだ。その場合は、
(jpg|gif|png)
といったパターンが利用できるだろう。
正規表現による置換
最後に、置換機能での正規表現の使い方を軽く紹介しておこう。正規表現による置換をマスターすれば、大量のデータを規則的に書き換えなければならない場合などに威力を発揮する。
もっともよく使いそうなのは、不要な文字を削除したいといったケースだろう。たとえば、“行末の不要な空白文字を削除する”場合は置換ダイアログで以下のように指定して[置換]ボタンを押せばよい。
- 検索する文字列:\s+?$
- 置換後の文字列:
“?”の意味については、コラム“欲張りなマッチと控えめなマッチ”を参照してほしい。
“$”というメタ文字は初めて利用したが、これは行の末尾にマッチする。よく似た役割のメタ文字として、ほかに行の先頭にマッチする“^”が存在する。
- ^:行の先頭と一致
- $:行の末尾と一致
たとえば、ソースコードのコメントを外すときなどに便利な“行頭の // を削除する”という処理は、
- 検索する文字列:^//
- 置換後の文字列:
で行える。もし余力があれば、このパターンを“行頭と“//”の間に空白文字が含まれている場合にも対応する”ように書き換えてみてほしい。これまでで学習したことの組み合わせで比較的簡単に実現できる。
さらに、文字列の入れ替えにも正規検索による置換は威力を発揮する。たとえば、“名,姓”というパターンの名前を“姓 名”に置き換えたい場合は、
- 検索する文字列:([^,]+),(.+)
- 置換後の文字列:\2 \1
とする。“\1”、“\2”はマッチした文字列のうち、カッコでグルーピングされている部分を表す特殊な記法で、“置換後の文字列”で利用することができる(ちなみに“\0”はマッチした文字列全体を表す)。これを利用すれば、文字列の入れ替えなども一発で行える。最初は使いこなすのが難しいかもしれないが、おいおい学習していけばよいだろう。
まとめ
筆者が考えるに、正規表現への入門につまづくパターンとしては、
- 例が自分の利用シーンに合致していない
- 一度に多くのことを覚えようとしてわけが分からなくなる
というケースが多いように感じる。そこで、前者に関しては紙幅の関係上どうしようもないところがあるが、後者については多少の工夫を試みた。一度にたくさんのことを覚えようとせず、まずは冗長だが汎用的な記法をマスターし、徐々に正規表現らしい短くてシンプルな表記へとチャレンジしていってほしい。
なお、「EmEditor」の検索・置換ダイアログには各種メタ文字・記法を入力するためのパレットが用意されている。[>]ボタンで簡単に呼び出せて、簡単なヘルプ代わりに使えるので活用しよう。
また、ヘルプページには正規表現を利用した実践的なサンプルが掲載されている。こうしたサンプルをコピー&ペーストで利用するだけでも、正規表現への理解を深めていくことができるだろう。
- EmEditor FAQ: 正規表現例を教えてください。
- https://jp.emeditor.com/help/faq/search/search_reg_exp_ex.htm
[制作協力:(株)エムソフト]