正規表現
出典: フリー百科事典『ウィキペディア(Wikipedia)』
正規表現(せいきひょうげん:regular expression)とは、文字列の集合を一つの文字列で表現する方法の一つ。正則表現(せいそくひょうげん)とも呼ばれ、形式言語理論の分野では比較的こちらの訳語の方が使われる。
もともと正規表現は形式言語理論において正規言語を表すための手段として導入された。形式言語理論では、形式言語が正規言語であることと正規表現によって表せることは同値である。
その後正規表現はテキストエディタ、ワードプロセッサをはじめとするアプリケーションソフトでパターンマッチ文字列を表すために使用されるようになり、表せるパターンの種類を増やすために本来の正規表現にはないさまざまな記法が新たに付け加えられた。このような拡張された正規表現には正規言語ではない文字列も表せるものも多く、ゆえに正規表現という名前は実態に即していない面もあるが、伝統的に正規表現と呼ばれ続けている。
この記事では主にこのような正規表現を用いたパターンマッチについて説明している。以下、誤解のない限り、アプリケーションソフトやプログラミングにおいて正規表現を用いた文字列のパターンマッチを行う機能のことを、単に正規表現という。
ほとんどのプログラミング言語では、構文またはライブラリによって正規表現を使うことができるようになっている。構文やライブラリに正規表現を備えたプログラミング言語やユーティリティとして、AWK、Sed、Perl、Python、Ruby、Java、JavaScript、PHPなどがある。
また、プログラミング言語の開発などに用いるlexも正規表現を使う。
それぞれの言語やアプリケーションで細部の仕様が異なっているが、POSIXにより標準規格も定められそれに準拠するものも増えてきてはいる。
目次 |
[編集] 基本的な概念
しばしばパターンと呼ばれる正規表現は、文字列群を表現する表現法である。通常、全ての要素をリストせずに文字列群を簡潔に表現するのに用いられる。例えば、Handel、Händel、Haendel という三つの文字列を含む集合は "H(ä|ae?)ndel" というパターンで表現できる(あるいは、パターンは個々の三つの文字列にマッチすると言われる)。ほとんどの形式では、もし特定の集合にマッチする何らかの正規表現が存在すれば、無限の数のそのような表現がある。ほとんどの形式では正規表現を構築するのに次の演算子を提供している。
- 選言
- 縦棒は選択肢を区切る。例えば、"gray|grey" は gray または grey にマッチし、これは普通 "gr(a|e)y" に短縮される。
- グループ分け
- 丸括弧はスコープと演算子の優先順位を定義するのに用いられる。例えば、"gr(a|e)y" では "(a|e)" の部分で a または e を示し、全体で gray または grey にマッチする。
- 量化
- 文字やグループの後ろの量化子は、直前の表現が何回現れることが許されるかを指定する。非常によく使われる量化子は ? と * と + である。
- ?
- 疑問符は直前の表現が0個か1個あることを示す。例えば、"colou?r" は color と colour にマッチする。
- *
- アスタリスクは直前の表現が0個以上あることを示す。例えば、"go*gle" は ggle、gogle、googleなどにマッチする。
- +
- プラス符号は直前の表現が1個以上あることを示す。例えば、"go+gle" は gogle や google などにマッチするが、ggleにはマッチしない。
これらの構文は任意の複雑な表現を形成するために組み合わされて使用される。
[編集] 文法
[編集] 伝統的な UNIX の正規表現
UNIX における基本正規表現の文法は POSIX によって旧式(obsolete)であるとされている。しかし、後方互換性のためにいまだに広く用いられている。ほとんどの正規表現を利用する UNIX のユーティリティ(grep や sed)ではデフォルトでこれを用いている。
この文法では、ほとんどの文字はリテラルに扱われる。つまり、ある文字はその文字にのみマッチする。例えば、"a" は a にマッチし、"(bc" は (bc にマッチするなど。例外はメタ文字と呼ばれる。
. | 任意の文字にマッチする。 |
[ ] | 括弧内に含まれる一文字にマッチする。例えば、[abc] は a、b、c にマッチする。英語のアルファベットでは、[a-z] は全ての小文字にマッチする。これらは混ぜることが出来る。[abcq-z] は a、b、c、q、r、s、t、u、v、w、x、y、z にマッチし、[a-cq-z]でも同様である。文字 '-' は括弧内の最初か最後にあるときのみ、リテラルに扱われる。例えば、[abc-] や [-abc]。[ や ] にマッチさせる最も手っ取り早い方法は、囲んでいる括弧内で、括弧が最初になるようにすることである。例えば、[][ab] は ]、[、a、b にマッチする。 |
[^ ] | 括弧内に含まれない一文字にマッチする。例えば、[^abc] は a、b、c 以外の任意の文字にマッチする。[^a-z] は小文字以外の任意の一文字にマッチする。上と同様にこれらは混ぜることが出来る。 |
^ | 行の最初にマッチする。 |
$ | 行の最後にマッチする。 |
\( \) | これに囲まれた表現は、後に呼び出すことが出来る。次の \n の項を参照のこと。 |
\n | ここで n は1から9までの数である。n 番目の \( \) で囲まれた部分にマッチする。この構文は理論的には不正で(正則文法の記述力を超える)、拡張正規表現では採用されていない。 |
* |
|
\{x,y\} | 直前の"ブロック"の x 回以上 y 回以下の繰り返しにマッチする。例えば、"a\{3,5\}" は aaa、aaaa、aaaaa にマッチする。 |
特定の正規表現の実装では、一部のメタ文字の前のバックスラッシュを異なって解釈する。例えば egrep や perl は、バックスラッシュの付いていない 括弧や縦棒 "|" をメタ文字と解釈し、バックスラッシュの付いているものをリテラルに解釈する。古いバージョンの grep は選言演算子 "|" をサポートしていない。
例
- ".at" は hat、cat、bat のような三文字の文字列にマッチする
- "[hc]at" は hat や cat にマッチする
- "[^b]at" は bat 以外の ".at" でマッチする全ての文字列にマッチする
- "^[hc]at" は行の最初にあるときだけ、hat や cat にマッチする
- "[hc]at$" は行の最後にあるときだけ、hat や cat にマッチする
文字列の範囲はロケールに依存する。例えば、エストニア語のアルファベットでは、s の後に z があり、その後は t、u、v、w、x、y と続くので、[a-z] ではすべての小文字のアルファベットにマッチしない[1]。そのため、POSIX 標準では次の表に示されているクラス、つまり文字の区分を定義している。
POSIX クラス | 対応する表現 | 意味 |
---|---|---|
[:upper:] | [A-Z] | 大文字 |
[:lower:] | [a-z] | 小文字 |
[:alpha:] | [A-Za-z] | アルファベット |
[:alnum:] | [A-Za-z0-9] | 数字とアルファベット |
[:digit:] | [0-9] | 数字 |
[:xdigit:] | [0-9A-Fa-f] | 16進数 |
[:punct:] | [.,!?:...] | 句読点 |
[:blank:] | [ \t] | スペースとタブ |
[:space:] | [ \t\n\r\f\v] | 空白文字 |
[:cntrl:] | 制御文字 | |
[:graph:] | [^ \t\n\r\f\v] | 印字文字 |
[:print:] | [^\t\n\r\f\v] | 印字文字とスペース |
例: [[:upper:]ab] は大文字と a と b のみにマッチする。
いくつかのツールで使用できる、POSIX にないクラスとして [:word:] がある。[:word:] は通常 [:alnum:] とアンダースコアからなる。これらが多くのプログラミング言語で識別子として使用できる文字であることを反映している。
[編集] POSIX の拡張正規表現
より現代的な拡張正規表現は多くの場合、現在の UNIX のユーティリティでコマンドラインオプションに "-E" を含めることで使用できる。
POSIX の拡張正規表現は伝統的な UNIX の正規表現に似ているが、いくつかの点で異なっている。
メタ文字 "+"、"?"、"|" が追加されている。また、バックスラッシュが削除されて、\{...\} は {...} になり、\(...\) は (...) になる。
"("、")"、"["、"]"、"."、"*"、"?"、"+"、"^"、"$" といった文字は特別な記号として使用されるので、リテラルに使いたいときはエスケープしなければならない。エスケープするには、それらの前に '\' を付ける。例えば、"a\.(\(|\))" は a.) や a.( にマッチする。
[編集] Perl 互換正規表現 (PCRE)
Perl は POSIX の拡張正規表現さえも上回る豊富な文法を持っている。その例として、POSIX とは異なり、Perl では最長マッチを行うか指定できることが挙げられる。例えば、パターン "a.*b" では .* はできるだけ長い文字列にマッチさせようとするが、パターン "a.*?b" ではできるだけ短い文字列にマッチさせようとする。だから "a bad dab" に対しては、前者のパターンでは文字列全体にマッチし、後者のパターンでは "a b" にだけマッチする。
このように Perl の正規表現が優れているため、多くの他のプログラミング言語やユーティリティなどで Perl の正規表現に非常によく似た文法を採用している。例えば、Java の Pattern クラス、Python、Ruby などがそうである。しかし、これらが Perl の正規表現と完全に互換である訳ではない。
[編集] 正規表現ライブラリ
言語的に、正規表現をサポートしていない場合においても、正規表現に必要な処理を提供する「正規表現ライブラリ」を導入することで正規表現を使うことができる。有名な正規表現ライブラリには「鬼車(おにぐるま)」がある。なお、鬼車は、Rubyの1.9系列に採用されている。
[編集] 形式言語理論における正規表現
アルファベット A = {a1,...,an} 上の正規表現は次のように定義される。正規表現の表す集合が、その正規表現の表す言語である。
- ∅ は正規表現である。これは空集合 ∅ を表す。
- ai(A の任意の要素)は正規表現である。これは ai のみからなる集合 { ai } を表す。
- X と Y が正規表現ならば、
- X|Y も正規表現である。これは X の表す集合と Y の表す集合の和集合を表す。
- XY も正規表現である。これは X に含まれる記号列に Y に含まれる記号列をつなげてできる記号列の集合 { ab | a ∊ X, b ∊ Y } を表す。
- X* も正規表現である。これは X に含まれる記号列を 0 個以上つなげて出来る文字列の集合 { an | a ∊ X, n ≥ 0 } を表す。
- 上記の帰納的導出によって構成される記号列のみが正規表現である。
正規表現の定義に、次の項目を含めることもある:
- ε は正規表現である。これは空記号列 ε のみからなる集合 { ε } を表す。
正規表現 ε の表す集合は正規表現 ∅* の表す集合に等しいので、ε を正規表現の定義に含めなくても ∅* で代用できる。
X|Y の代わりに X+Y と書くことや、XY の代わりに X·Y と書くこともある。また、「|」や「*」の優先順位を明確にするために括弧を使うこともある。
[編集] 関連項目
[編集] 参考文献
- 詳説 正規表現 ISBN 4873111307
[編集] 脚注
- ^ 正規表現として a-z を使用していたことが原因のバグ
[編集] 外部リンク
- 正規表現パズル - 正規表現の問題集
- 正規表現メモ - sed, grep, perlなど様々なソフトの正規表現がまとめられている
- 正規表現/文字コード最新リンク2005
- Regular Expression(Riue ちゃんの正規表現講座) - Index