正規表現とは?
正規表現は特殊な意味を持たせた記号を使って数字・文字列を表現する方法のことです。特殊な意味を持つ記号をメタキャラクタといいます。身近なところでも正規表現と似たものが使われています。例えば、
人気の○○とは?
の○○がメタキャラクタといえます。○○に入るのが何文字か?数字はOKかなどとより細かい意味をもつ記号を使うのが正規表現ですね(注:実際はワイルドカードと正規表現は別物)
なんとなくイメージがつかめたでしょうか?この正規表現は文字列の検索、指定などに使います。
実際のメタキャラクタの例
例えば「.」は正規表現では任意の一文字(文字・数字)を表す記号です。これを使って「..県」と書いたら何が当てはまるでしょうか?
例えば、「秋田県」や「福岡県」「12県」も当てはまります。一方で「和歌山県」は当てはまりません。文字数が多いからです。
メタキャラクタは.以外にも+, {}< % $ ^などたくさんあります。
正規表現は初めのうちは読み取ることも組み立てることも難しく感じますが、メタキャラクタの意味を理解さえしてしまえば読み取るのは比較的簡単です。
正規表現の難しいところは例外が少なく、マッチ率の高い表現をいかに組み立てるところにあります。
例えば先ほどの「..県」という正規表現は鹿児島県などの4文字の県は検索からもれます。「...県」としたら逆に2文字の県がもれてしまいます。次に「.{2,3}県」とすると2+3文字県はマッチします。しかし都道府県でみると東京都や北海道などはマッチしません。
都道府県にマッチするような正規表現は以下のようになります。
(東京都|北海道|(?:京都|大阪)府|.{2,3}県)
https://gist.github.com/HaiTo/9afc564ccfaba80040bc
上の正規表現なら万全かと思いきやそうではないです。都道府県を漢字で書いてくれるとは限らず、また東京 都のようにスペースを空けるかもしれません。こうした例外はある経験や試行錯誤が必要になってくるところでもあります。精度ができるだけ高ければよいか?というとそうでもないです。正規表現が複雑になってしまうからです。このように目的を達するために必要な正規表現を精度高く組み立てることが難しいところです。
正規表現で注意すべきところをまとめると
- 正規表現は使用するプログラムによって表現が若干異なる
- 100%マッチする正規表現を作るのは困難
- 文字サンプルの把握、使用用途や精度を予め考えておくべき
- 同じことを表現する正規表現は複数存在する
正規表現は大量のテキストデータから目的の文字列を探したり、置換する、迷惑メールを振り分けたり、フォームの入力で誤った入力をはじいたりなど様々な応用先があります。例えば以下の正規表現は何を表しているでしょうか?
^\d{3}-\d{4}$
これは郵便番号を表す正規表現です。100-0013などがマッチします。これの例外はなんでしょうか?ハイフン無しの郵便番号はこれでは引っ掛かりません。しかし、ハイフン無しがサンプルに入っていないなら問題はないです。
これ以降は正規表現の基礎として基本的な正規表現で使用されるメタキャラクタの説明や使い方などを紹介していきます。
正規表現の基礎
正規表現はそれだけで一冊の本を書くことができるくらいに幅広く、深いもジャンルです。正規表現は英語や日本語、あるいはC言語やJAVA言語のように複数の方言があります。このことが正規表現を難しくしている一つの理由です。
しかし、いくら多様性のある正規表現でも基本の型となる正規表現があります。その中でも基本的かつ実用的な正規表現として拡張正規表現を理解することが重要です。本記事では3つの基本となる正規表現を中心に取り上げて解説していきます。
正規表現の違い
正規表現には方言のように使用されるプログラムによって若干の違いがあります。そのため、あるプログラムで使っている正規表現を別の場所で利用すると同じように動かないことがあります。
とはいえ、基本的な使い方は共通しているのでよく使うプログラムや基本的な表現に焦点を当てて解説していきます。
取り上げる正規表現は
- 基本正規表現(BRE) POSIX標準
- 拡張正規表現(ERE) POSIX標準
- Perl正規表現 (PCRE)
です。
基本正規表現
たくさんある正規表現も独自に生まれたわけではなく、型となる正規表現から派生・拡張して生まれていきました。中でも最も基本となる正規表現が基本正規表現(BRE)です。BREとその機能拡張版である拡張正規表現(ERE)です。この2つはUNIX/Linux環境であればどこでも利用できるという汎用性の高さが特徴です。
Linuxにおいて最も基本的かつ、よく利用する正規表現を使用するプログラムはegrep(grep)だと思います(シェルにもメタキャラクタがある)。
grepとegrepはマッチする文字列を表示するコマンドですが、両者で使用される正規表現は異なります。grepで使われる正規表現は基本正規表現(BRE)です。BREはgrep以外にもsedでも使われています。
grepでは基本はBREですが、拡張正規表現もperl正規表現もオプションを指定することで扱えるようになります。grepの使い方によってはそれほど強力な正規表現は必要ないので基本正規表現で十分ですが、いくつかのメタキャラクタを使用したい場合はegrep(拡張正規表現)を使用します。
BREもEREも基本的な部分は同じであるため、BREとEREの違いに焦点を当てたほうが理解しやすいと思います。学ぶ順番としてもBRE→EREとするまでもなくこれらを同時に学んでも平気だとおおもいます。むしろ正規表現として利用するのはEREのほうかと思います。(BREはgrepやsedで利用できるがEREも使える)
基本正規表現にないメタキャラクタは実質一つ
- ? 直前の文字を0~1回くりかえし
- + 直前の文字を1回以上くりかえし
- { } {n} 直前の文字をn回 {n,}n回以上 {n,m}n回以上m回以内繰り返し
- | またはの意味をもつ (A|B) AまたはB ←実質これだけBREに無い
- ( ) 正規表現のグループ化
上記のメタキャラクタはそのままBREでは利用できませんが代替表現が利用できます。しかし、「|」を使いたい場合はEREを使う必要があります。
「(」と「{」はバックスラッシュ「\」でエスケープすることによって使用することができます。「\( xxxx \)」のように使います。また、「? 」=「\{0,1\}」「+」 = 「\{1,\}」と同じ意味であるためBREでも表現可能です。
拡張正規表現
拡張正規表現は上記で挙げた基本正規表現(BRE)では使えない5つのメタキャラクタがそのまま利用可能です。{や(はエスケープする必要はありません。逆に言えば、?, +, (, {, |をただの文字列とする場合はエスケープする必要があります。つまり、拡張正規表現と基本正規表現はメタキャラクタの数くらいしか違いがないということです。
正規表現で使われるメタキャラクタ
正規表現で使用されるメタキャラクタについて説明します。気を付けなければならないのはシェルで使うワイルドカードのメタキャラクタと正規表現のメタキャラクタは異なる点です。ワイルドカードの「*」は任意の0文字以上の文字列を表しますが正規表現では直前の文字が0回以上の繰り返しと違った意味を持ちます。ここでは正規表現で使われるメタキャラクタを説明します。「\」はメタキャラクタ→普通の文字、普通の文字→メタキャラクタというように変換できます。*は元々メタキャラクタですが、\*とエスケープすると文字になり、逆にdをバックスラッシュでエスケープ「\d」とすることで数字[0-9]を表すメタキャラクタになります。
- アンカー
- ^ 文字の先頭
- $ 文字の行末
- \< 単語の先頭
- \> 単語の末尾
- 量指定子
- * 前の文字0回以上の繰り返し
- + 前の文字1回以上の繰り返し
- ? 前の文字0~1回以上の繰り返し
- {n,m} n回以上m回以内の繰り返し {0,1}は?と同じ
- 文字クラス
- . 任意の一文字
- \s スペース
- \w アルファベットと数字
- \W アルファベットと数字以外
- [ ] かっこ内の文字いずれか
- [0-9] 0~9の数字いずれか1つ
- [a-z] 小文字の英語
- [^] かっこ内の文字以外
- その他
- | または (yes|no) yesまたはnoのいずれか
- () 上記参照、単語を区切ったりするかっこ
アンカー
アンカーは文字の位置を表すメタキャラクタです。
「This is a pen」という文章があれば、行頭はThis is ~なので
^This is と指定すれば行頭のThis is を指定できます。
~penが行末なので .+pen$と表現できます。
行の先頭、もしくは単語の先頭(前にスペース)がある文字を表すには「\<」逆に単語の末尾を表すには「\>」を使います。
例えば「Apple BigApple」という文で
- egrep ‘Apple’ → Apple BigApple Apple
- egrep ‘^Apple’ → Apple BigApple Apple
- egrep ‘\<Apple’ → Apple BigApple Apple
- egrep ‘Apple\>’ → Apple BigApple Apple
- egrep ‘Apple$’ → Apple BigApple Apple
このように指定の仕方によってマッチする部分が違います。
量指定子
量指定子は文字の繰り返し量を指定するメタキャラクタです。
例えば「ウリ ウリィィィィ」という文にある単語の「ィ」は4つ続いています。
- egrep ‘ウリィ+’ → ウリ ウリィィィィ
- egrep ‘ウリィ*’ → ウリ ウリィィィィ
- egrep ‘ウリィ?’ → ウリ ウリィィィィ
*は前の文字を繰り返さなくても良いのでウリもマッチします。?は前の文字0か1の繰り返しなのでウリとウリィがマッチします。+は必ず前の文字が入るのでウリはマッチしません。なぜか*を使いがちですが、+のほうが好ましいことが多いです。*は前の文字を含まなくても良いので予期しない単語とマッチしてしまうことがあるからです。上記の例のようにウリもマッチしてしまいます。
文字クラス
それ自体が文字となるようなメタキャラクタです。
よく使う「.」は任意の一文字を表します。これを量指定子と組み合わせることで多様な表現が可能です。「.」の不用意な使いすぎは予期しない単語をマッチさせてしまうので気を付けましょう。数字でよい場合は[0-9]などを使いましょう
[ ]はその中の文字一文字を表す表現です。()とは意味が違うので注意してください。A[pple]でAppleはヒットしません。ApやAlなどがマッチします。
[ ]を使うときに注意したいのは 「–」に特別な意味がある点です。[0-5]は 0, – , 5を表すのではなく、0,1,2,3,4,5を表します。