\\1:マッチした文字を表す
$ori = "聖徳太子は千円札だっけ?"; $target = "は(.*?)札"; $replace = "は五\\1札"; $str = mb_ereg_replace( $target, $replace, $ori ); echo $str;
実行結果
聖徳太子は五千円札だっけ?
出典(authority):フリー百科事典『ウィキペディア(Wikipedia)』「2017/11/05 13:38:39」(JST)
正規表現(せいきひょうげん、英: regular expression)とは、文字列の集合を一つの文字列で表現する方法の一つである。正則表現(せいそくひょうげん)とも呼ばれ、形式言語理論の分野では比較的こちらの訳語の方が使われる。まれに正規式と呼ばれることもある。
もともと正規表現は形式言語理論において正規言語を表すための手段として導入された。形式言語理論では、形式言語が正規言語であることと正規表現によって表せることは同値である。
その後正規表現はテキストエディタ、ワードプロセッサをはじめとするアプリケーションでパターンマッチ文字列を表すために使用されるようになり、表せるパターンの種類を増やすために本来の正規表現にはないさまざまな記法が新たに付け加えられた。このような拡張された正規表現には正規言語ではない文字列も表せるものも多く、ゆえに正規表現という名前は実態に即していない面もあるが、伝統的に正規表現と呼ばれ続けている。
この記事では主にこのような正規表現を用いたパターンマッチングについて説明している。以下、誤解のない限り、アプリケーションやプログラミングにおいて正規表現を用いた文字列のパターンマッチングを行う機能のことを、単に正規表現という。
ほとんどのプログラミング言語では、構文またはライブラリによって正規表現を使うことができるようになっている。構文やライブラリに正規表現を備えたプログラミング言語やユーティリティとして、grep、AWK、sed、Perl、Tclなどがある。
また、プログラミング言語の開発などに用いるlexも正規表現を使う。
それぞれの言語やアプリケーションで細部の仕様が異なっているが、POSIXやECMAScriptにより標準規格も定められ、それらに準拠するものも増えてきてはいる。
理論的に明解であり扱いも容易であるため、形式的な説明を先に述べる。
記号(アルファベット) A = {a1,...,an} 上の正規表現は次のようなものから成る。正規表現があらわす記号列(アルファベット列)の集合によって形式言語が定義される。
正規表現の定義に、次の項目を含めることもある:
正規表現 ε の表す集合は正規表現 ∅* の表す集合に等しいので、ε を正規表現の定義に含めなくても ∅* で代用できる。
X|Y の代わりに X+Y と書くことや、XY の代わりに X·Y と書くこともある。また、「|」や「*」の優先順位を明確にするために、補助的なカッコも(上述の定義には含めていないが)必要である。
以下ではもっぱらよく使われているライブラリやツール等の実用的な観点から説明する。
例えば、「Handel」、「Hendel」、「Haendel」 という三つの文字列を含む集合は 「H(e|ae?)ndel」 というパターンで表現できる(あるいは、パターンは個々の三つの文字列にマッチすると言われる)。ほとんどの形式では、もし特定の集合にマッチする何らかの正規表現が存在すれば、無限の数のそのような表現がある。ほとんどの形式では正規表現を構築するのに次の演算子を提供している。
これらの構文は任意の複雑な表現を形成するために組み合わされて使用される。
正規表現の起源は、いずれも理論計算機科学の一分野であるオートマトン理論や形式言語理論にみることができる。これらは計算のモデル化(オートマトン)や形式言語の分類方法などを扱う学術分野である。数学者のスティーヴン・クリーネは1950年代に正規集合と呼ばれる独自の数学的表記法を用い、これらの分野のモデルを記述した。ケン・トンプソンはテキストファイル中のパターンにマッチさせる手段として、この表記法をエディタQEDに導入した。彼はこの機能をUNIXのエディタedにも追加し、後に一般的な検索ツールであるgrepの正規表現へと受け継がれていった。これ以降、トンプソンの正規表現の適用にならい、多くのUNIX系のツールがこの方法を採用した(例えば expr、awk、Emacs、vi、lex、Perl など)。
PerlとTclの正規表現はヘンリー・スペンサーによって書かれたものから派生している(Perlは後にスペンサーの正規表現を拡張し、多くの機能を追加した)。フィリップ・ヘーゼルはPerlの正規表現とほぼ互換のものを実装する試みとしてPerl Compatible Regular Expressions (PCRE) を開発した。これはPHPやApacheなどといった新しいツールで使用されている。Perl 6では、正規表現の機能を改善してその適用範囲や能力を高め、Parsing Expression Grammarを定義できるようにする努力がなされた。この結果として、Perl 6文法の定義だけでなくプログラマのツールとしても使用できる、Perl 6 rulesと呼ばれる小言語が生み出された。これらの規則は正規表現の機能のすべてを保持しながら、副規則を通して再帰下降構文解析のバッカス・ナウア記法の定義を行うことができる。
構造化情報標準における、文書やデータベースのモデル化に対する正規表現の使用は重要である。これは1960年代に始まり、ISO SGMLのような産業標準が確立された1980年代に拡大した。構造規定言語の標準の中核は正規表現である。より単純かつ明白な例としては、DTD要素グループの構文において正規表現が使われている。
UNIXの標準であるPOSIXでは、「simple regular expressions」「basic regular expression (BRE)」「extended regular expression (ERE)」の3種類の記法が示されている。このうち、「simple regular expressions」は「歴史的(英: historical)」また「レガシー(英: legacy)」と書かれており、後方互換性を提供するものとされ、標準の将来の版では廃止され得る(may be withdrawn)と注意されている。
simple regular expressionsの仕様は「regexp.h
」のマニュアルページとして示されている。[1]
基本正規表現とも。ほとんどの正規表現を利用する UNIXのユーティリティ(grepやsed)のデフォルトはこれである。[2]
この文法では、ほとんどの文字はリテラル(機能を意味せず書かれたそのまま)に扱われる。つまり、ある文字はその文字にのみマッチする。例えば、正規表現「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] 」は一文字「a 」、「b 」 、「c 」 、「- 」にマッチする。一文字「[ 」や「] 」自身にマッチさせる最も手っ取り早い方法は、囲んでいる括弧内で、括弧が最初になるようにすることである。例えば正規表現「[][ab] 」は一文字「] 」、「[ 」、「a 」、「b 」にマッチする。 |
[^…] |
括弧内に含まれない一文字にマッチする。例えば正規表現「[^abc] 」は「a 」、「b 」、「c 」以外の任意の文字にマッチする。正規表現「[^a-z] 」は小文字以外の任意の一文字にマッチする。上と同様にこれらは混ぜることが出来る。 |
^ |
行の最初にマッチする。 |
$ |
行の最後にマッチする。 |
(…) |
これに囲まれた表現は、後に呼び出すことが出来る。次の \1 、…、\9 の項を参照のこと。 |
|
それぞれ「( 」と「) で囲まれた部分に先行してマッチした1~9 番目の文字列と同じ文字列パターンにマッチする。この機能は理論的には、言うならば非正規で(正規言語の記述力を超える)、POSIX拡張正規表現では採用されていない。 |
* |
|
{m,n} |
直前のブロックの m 回以上 n 回以下の繰り返しにマッチする。例えば、正規表現「a{3,5} 」 は文字列「aaa 」、「aaaa 」、「aaaaa 」にマッチする。 |
特定の正規表現の実装では、一部のメタ文字の前のバックスラッシュを異なって解釈する。例えば egrep や Perl は、バックスラッシュの付いていない括弧や縦棒「|
」をメタ文字と解釈し、バックスラッシュの付いているものをリテラルに解釈する。古いバージョンの grepは選言演算子「|
」をサポートしていない。
例
.at
」は文字列「hat
」、「cat
」、「5at
」のような3文字の文字列にマッチする[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]
」ではすべて言語のすべてのアルファベット小文字のにマッチするわけではない[3]。そのため、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
」~「Z
」と「a
」と「b
」のうち一文字のみにマッチする。
いくつかのツールで使用できる、POSIX にないクラスとして「[:word:]
」がある。「[:word:]
」は通常「[:alnum:]
」とアンダースコアからなる。これらが多くのプログラミング言語で識別子として使用できる文字であることを反映している。
拡張正規表現とも。より現代的な拡張正規表現は多くの場合、現在の UNIXのユーティリティでコマンドラインオプションに「-E
」を含めることで使用できる。[4]
POSIXの拡張正規表現は伝統的な UNIX の正規表現に似ているが、いくつかの点で異なっている。
基本正規表現 | 拡張正規表現 |
---|---|
(対応なし) | + |
(対応なし) | ? |
(対応なし) | | |
\{…\} |
{…} |
\(…\) |
(…) |
( |
\( |
) |
\) |
[ |
\[ |
] |
\] |
. |
\. |
* |
\* |
? |
\? |
+ |
\+ |
^ |
\^ |
$ |
\$ |
例えば、拡張正規表現「a\.(\(|\))
」は文字列「a.)
」や 文字列「a.(
」にマッチする。
GNU findコマンドにおけるデフォルトの正規表現文法としても用いられる。(findutils-4.2.28)
GNU Emacs Manual - Regexps
PerlはPOSIXの拡張正規表現さえも上回る豊富な文法を持っている。その例として、POSIXとは異なり、Perlの正規表現には「非欲張り量指定子」がある。標準の「*
」は、例えば正規表現「a.*b
」の「.*
」はできるだけ長い文字列にマッチしようとする。このふるまいを「貪欲」という。たとえば文字列「a bad dab
」にマッチさせると、全体にマッチする。これに対し、Perlでは使うことができる正規表現「a.*?b
」の「.*?
」は、マッチするのであれば、できるだけ短い文字列にマッチする。たとえば文字列「a bad dab
」に対して「a b
」にだけマッチする。これを「非欲張り量指定子」と言う。
また、Perlには以下の定義済み文字クラスがある。
メタ文字 | マッチする対象 |
---|---|
\d |
アラビア数字、つまり「[0-9] 」 |
\D |
アラビア数字以外の文字、つまり「[^\d] 」 |
\w |
アルファベット、アラビア数字またはアンダーバー、つまり「[a-zA-Z_0-9] 」(ロケールに依存し、例えばウムラウト付き文字などの扱いが変わる) |
\W |
アルファベット、数字やアンダーバー以外の文字、つまり「[^\w] 」 |
\s |
空白文字、つまり大抵の制御文字クラス ASCII文字集合のフォームフィード文字、ラインフィード文字、キャリッジリターン文字、水平タブ文字、垂直タブ文字[どこ?] |
\S |
空白文字以外の文字、つまり、[^\s] |
すぐれた機能をもつPerlの拡張正規表現は、多くのプログラミング言語やソフトウェアで採りいれられている。例えば、JavaのPatternクラス、Python、Rubyなどがそうである。しかし、これらがPerlの正規表現と完全に互換である訳ではない。また、Perl Compatible Regular Expressions (PCRE) と呼ばれる汎用の正規表現ライブラリはアプリケーションに組み込まれ、Perlの正規表現とほぼ互換の機能を提供する。
言語処理系やアプリケーションが正規表現をサポートしていない場合にでも、正規表現に必要な処理を提供する正規表現ライブラリを導入することで正規表現を使うことができる。以下にその一例を挙げておく。
[ヘルプ] |
[a-z]
」を使用していたことが原因である。
ウィキブックスに正規表現関連の解説書・教科書があります。 |
|
|
全文を閲覧するには購読必要です。 To read the full text you will need to subscribe.
関連記事 | 「表現」「正規」 |
.