PHPで、正規表現(パターンマッチ)を使おう!
正規表現(せいきひょうげん、regular expression)とは、文字列の集合を一つの文字列で表現する方法の一つである。
正規表現とは【regular expression】 - IT用語辞典
文字列のパターンを表現する表記法。文字列の検索・置換を行うときに利用される。
PHP 正規表現の基本 (preg_match) - どうにかなるBLOG | http://sandman.s6.xrea.com/nucleus/item-62.html |
サルにもわかる正規表現入門 | http://www.mnet.ne.jp/~nakama/ |
正規表現の解説 初級編 | http://www4.ocn.ne.jp/~kaerume/k2e/regex_1.html |
図解でみる正規表現入門 | http://funcchan.blog16.fc2.com/ |
正規表現/PHP入門 | http://www.scollabo.com/banban/php/php_15.html |
よく使う正規表現 - PHP入門(正規表現3) - イクケン | http://labo.iix.co.jp/?p=573 |
PHPでは、正規表現を扱う関数が3種類用意されています。
http://www.php.net/manual/ja/refs.basic.text.php
関数 | 機能 | マルチバイト文字 |
POSIX拡張正規表現関数 | POSIX拡張正規表現を使用した正規表現関数 | マルチバイト文字には対応していない |
PCRE関数 | Perlの正規表現に似た構文を持つ正規表現関数 | UTF-8には対応しているが、他のマルチバイト文字には対応していない |
マルチバイト文字列関数 | マルチバイト対応の文字列関数(mbstring)の正規表現関数 | マルチバイト文字に対応している |
PHP 5.3.0 以降、POSIX 正規表現 拡張モジュールは非推奨となりました。
http://www.php.net/manual/ja/ref.regex.php
ereg_replace | 正規表現による置換を行う |
ereg | 正規表現によるマッチングを行う |
eregi_replace | 大文字小文字を区別せずに正規表現による置換を行う |
eregi | 大文字小文字を区別せずに正規表現によるマッチングを行う |
split | 正規表現により文字列を分割し、配列に格納する |
spliti | 大文字小文字を区別しない正規表現により文字列を分割し、配列に格納する |
sql_regcase | 大文字小文字を区別しないマッチングのための正規表現を作成する |
http://www.php.net/manual/ja/book.pcre.php
preg_filter | 正規表現による検索と置換を行う |
preg_grep | パターンにマッチする配列の要素を返す |
preg_last_error | 直近の PCRE 正規表現処理のエラーコードを返す |
preg_match_all | 繰り返し正規表現検索を行う |
preg_match | 正規表現によるマッチングを行う |
preg_quote | 正規表現文字をクオートする |
preg_replace_callback | 正規表現検索を行い、コールバック関数を使用して置換を行う |
preg_replace | 正規表現検索および置換を行う |
preg_split | 正規表現で文字列を分割する |
http://php.net/manual/ja/ref.mbstring.php
mb_ereg_match | マルチバイト文字列が正規表現に一致するか調べる |
mb_ereg_replace | マルチバイト文字列に正規表現による置換を行う |
mb_ereg_search_getpos | 次の正規表現検索を開始する位置を取得する |
mb_ereg_search_getregs | マルチバイト文字列が正規表現に一致する部分があるか調べる |
mb_ereg_search_init | マルチバイト正規表現検索用の文字列と正規表現を設定する |
mb_ereg_search_pos | 指定したマルチバイト文字列が正規表現に一致する部分の位置と長さを返す |
mb_ereg_search_regs | 指定したマルチバイト文字列が正規表現に一致する部分を取得する |
mb_ereg_search_setpos | 次の正規表現検索を開始する位置を設定する |
mb_ereg_search | 指定したマルチバイト文字列が正規表現に一致するか調べる |
mb_ereg | マルチバイト文字列に正規表現マッチを行う |
mb_eregi_replace | マルチバイト文字列に大文字小文字を区別せずに正規表現による置換を行う |
mb_eregi | マルチバイト文字列に大文字小文字を区別しない正規表現マッチを行う |
mb_regex_encoding | 現在の正規表現用のエンコーディングを文字列として返す |
mb_regex_set_options | マルチバイト正規表現関数のデフォルトオプションを取得または設定する |
mb_split | マルチバイト文字列を正規表現により分割する |
http://php.net/manual/ja/reference.pcre.pattern.syntax.php
以下、preg_match()等、PCRE関数の使い方のまとめです。
PHPマニュアルの和訳は、ちょっと文章が硬くて分かりづらいですね><
http://www.php.net/manual/ja/regexp.reference.delimiters.php
PCRE 関数を使うときには、パターンを delimiters で囲まなければなりません。
英数字、バックスラッシュ、空白文字以外の任意の文字をデリミタとして使うことができます。
デリミタとしてよく使われる文字は、スラッシュ (/)、 ハッシュ記号 (#) およびチルダ (~) です。
次に示す例は、どれも正しいデリミタです。
#code(php){{
/foo bar/
#^[^0-9]$#
例: $pattern = '/abc/';
メタ文字=文字列の構造(文字の繰り返し等)を表現するために使われる特殊文字の事。
http://www.php.net/manual/ja/regexp.reference.meta.php
正規表現の強力さは、パターン中に選択肢や繰り返しを記述できることにあります。
選択肢や繰り返しは、メタ文字 (meta-character) を使ってパターン中に記述します。
メタ文字は、その文字自体を表わさず、代わって特別な解釈が行われます。
メタ文字には、2種類あります。
ひとつは、角カッコ内を除き、パターン中のどこででも使用できる文字です。
もうひとつは、角カッコで括られた中でだけ使用できる文字です。
メタ文字 | 機能 |
\ | 多目的に使う一般的なエスケープ文字 |
^ | 検索対象(複数行モードでは行)の始まりを言明 |
$ | 検索対象(複数行モードでは行)の終わりを言明 |
. | 改行を除くすべての文字にマッチ(デフォルト時) |
[ | 文字クラス定義の開始 |
] | 文字クラス定義の終了 |
| | 選択枝の開始 |
( | サブパターンの開始 |
) | サブパターンの終了 |
? | ( の意味を拡張/0 または 1 回マッチ/なるべく少ない回数だけマッチ (繰り返し を参照) |
* | 0回以上の繰り返し |
+ | 1回以上の繰り返し |
{ | 最小/最大を指定する量指定子の開始 |
} | 量指定子の終了 |
パターン中の角カッコで括まれた部分を「文字クラス」と言います。 文字クラスで使えるメタ文字は、次のものだけです。
メタ文字 | 機能 |
\ | 一般的なエスケープ文字 |
^ | クラスの否定。ただし、文字クラスの最初の文字に用いた場合のみ |
- | 文字の範囲の指定 |
] | 文字クラスの終了 |
メタ文字の「メタ」(meta)とは、「超」という意味。
http://www.mnet.ne.jp/~nakama/regexp1.html
特殊文字を正規表現では、「メタ文字」と呼んでいます。
「メタ」というのは、「超」と言う意味で、あの「チョーむかつく」の「チョー」と同じ意味です。
普通の文字以上の意味を含んでいるという意味になるかと思います。
http://www.php.net/manual/ja/regexp.reference.escape.php
正規表現で使われるメタ文字(「*」や「+」等の文字)を、正規表現のパターンとして使いたい場合、エスケープ文字(英語環境ではバックススラッシュ=半角の「\」、日本語環境では円記号=半角の「¥」)を前に付けると、メタ文字ではなく普通の文字として扱える。
バックスラッシュ〔日本語環境では円記号となる場合もある〕には、 いくつかの使用法があります。
ひとつめの使用法は、非英数字の前に記述する場合で、続く文字が表す特別な意味を取り去ります。
このエスケープ文字としての使用法は、文字クラスの内外部いずれでも可能です。
例: $pattern = '/12\*89/';
検索・置換したい文字列の中に、改行やタブなどの非表示文字がある場合、エスケープシーケンスを使う。
バックスラッシュの 2 番目の使用法は、非表示文字〔制御コードなど〕をパターン中に目に見える形で記述するための方法です。
ヌル文字はパターンを終了させてしまうため使えませんが、その他の非表示文字は、パターンにそのまま含めても問題はありません。しかし、パターンの編集には、バイナリ文字をそのまま用いるよりも、以下に示すエスケープシーケンスを用いる方が便利でしょう。
(例)
エスケープシーケンス | 意味 |
\n | 改行 (newline) |
\t | タブ |
バックスラッシュの第3の使用法は、包括的な文字型を指定する用途です。
(例)
エスケープシーケンス | 意味 |
\d | 10進数字 |
\s | 空白文字 |
バックスラッシュの第 4 の使用法は、簡単な言明 (assertion) です。
言明とは、マッチがある特定の位置でだけ可能だという条件を指定するもので、検索対象文字列から文字を消費 (consume)〔つまり文字自体にマッチ〕しません。
サブパターンを使ったより複雑な言明の方法もありますが、それについての解説は後ほど行います。
バックスラッシュを使った言明は、次のものがあります
(例)
エスケープシーケンス | 意味 |
\G | マッチングの開始位置 |
\A | 検索対象文字列の始端(複数行モードとは独立) |
\Z | 検索対象文字列の終端、または終端の改行(複数行モードとは独立) |
http://www4.ocn.ne.jp/~kaerume/k2e/regex_1.html#b3_3
\A
文字列の最初
文字列の最初にマッチします。
マッチ対象文字列が複数行になっていても、その文字列の一番最初の位置にだけマッチします。
\Z
文字列の最後
文字列の最後にマッチします。
マッチ対象文字列が複数行になっていても、その文字列の一番最後の位置にだけマッチします。
http://www.php.net/manual/ja/regexp.reference.unicode.php
アンカーは、文字列内の特定の位置(行頭、行末など)を表すもの。
通常、マッチするのは「文字」に対してだが、アンカーは「位置」に対してマッチする。
http://www.php.net/manual/ja/regexp.reference.anchors.php
ハット記号 (^)
マッチング位置が対象文字列の始端
ドル記号 ($)
マッチング位置が 対象文字列の終端にあるか、文字列の終わりの改行文字の直前にある場合
http://www4.ocn.ne.jp/~kaerume/k2e/regex_1.html#b3_3
^
行頭
行のはじめの位置にマッチします。始めの文字ではありませんので注意して下さい。
\n」の次(文字列があれば)には必ず「^」があることになります。
$
行末
行の終端位置にマッチします。終わりの文字ではありません。
http://www.php.net/manual/ja/regexp.reference.dot.php
パターン中のドット(ピリオド、終止符)は、文字クラス外では、対象文字列の任意の 1文字にマッチします。
非出力文字も含まれます。
ただし、(デフォルトでは)改行文字とはマッチしません。
http://www4.ocn.ne.jp/~kaerume/k2e/regex_1.html#b3_2
「.」(ピリオド)は、改行を除く任意の1文字を表す。
http://www.php.net/manual/ja/regexp.reference.character-classes.php
開き角カッコは文字クラス (character class) の開始を表し、閉じ角カッコにより文字クラスは終了します。
閉じ角カッコだけでは、特別な意味を持ちません。
閉じ角カッコを文字クラスのメンバとしたい場合は、文字クラスの最初の文字(否定のハット記号がある場合はその直後)とするか、バックスラッシュでエスケープする必要があります。
文字クラスは、検索対象文字列のたかだか1文字にマッチします。
マッチする文字は、その文字クラスによって定義された文字集合のうちのどれかです。
ただし、文字クラスの最初の文字がハット記号の場合は、マッチする文字は、その文字クラスに定義されていない文字となります。
ハット記号自体をクラスのメンバとしたい場合は、文字クラスの最初の文字としないか、バックスラッシュでエスケープしてください。
ワォ~!PHPマニュアルの文章は硬い!(訳分からんw)
http://www.php.net/manual/ja/regexp.reference.alternation.php
縦線は、パターンに選択肢 (alternative) を列挙するために使われます。
例えば、パターンgilbert|sullivanは、"gilbert" または "sullivan" にマッチします。
選択肢の数に制限はありません。
また、空の選択肢も可能です (空の文字列にマッチします)。
マッチの手順としては、各選択肢が左から右に順にマッチするかどうか試行され、最初にマッチに成功した選択肢が使われます。
http://www.php.net/manual/ja/regexp.reference.internal-options.php
http://www.php.net/manual/ja/regexp.reference.subpatterns.php
サブパターンは、丸カッコで括られたパターンのことで、ネストも可能です。
パターンの一部をサブパターンにすると、以下の 2 つのことが可能になります。
1.選択肢の範囲の指定 (localize)。
例えば、パターン cat(aract|erpillar|) は、単語 "cat", "cataract", "caterpillar" にマッチします。
カッコをつけないと、このパターンは、"cataract", "erpillar" または空の文字列にマッチしてしまいます。
2.サブパターンによる値の取得(キャプチャ)。
パターン全体としてマッチに成功した場合、対象文字列の内、サブパターンにマッチした部分の値がコールした側に (pcre_exec() の引数 ovector で) 返されます。
開きカッコの数が(1 から始まって)左から右に数えられ、キャプチャ用サブパターン (capturing subpattern) の番号が指定されます。
例えば、文字列 "the red king" に対し、パターン
the ((red|white) (king|queen))をマッチングさせた場合、キャプチャされる部分文字列は、 "red king", "red", "king" であり、 それぞれ 1 番, 2 番, 3 番と番号がふられます。
http://www.php.net/manual/ja/regexp.reference.repetition.php
繰り返し (repetition) は、量指定子 (quantifier) を使って指定します。
量指定子は、以下の要素の後に付けることが出来ます。
http://www.php.net/manual/ja/regexp.reference.back-references.php
http://www.php.net/manual/ja/regexp.reference.assertions.php
言明 (assertion) とは、カレントのマッチング位置の直前・直後の文字に対する テストであり、文字を消費 (consume)〔つまり文字自体にマッチ〕しません。
単純な言明コード \b, \B, \A, \Z, \z, ^ および $ については、前述しました。
より複雑な言明は、サブパターンを用いて記述します〔言明サブパターン (assertion subpattern) と呼ばれる〕。
言明サブパターンには、2種類あります。
対象文字列においてカレントの位置の先を読むものと、後ろを読むものです。
先読み言明 (lookahead assertion) は、 肯定の言明 (positive assertion) の場合 (?= で始まり、 否定の言明 (negative assertion) の場合 (?! で始まります。
戻り読み言明は、肯定の言明の場合 (?<= で始まり、 否定の言明の場合 (?<! で始まります。
(参考)
http://www.upken.jp/kb/ybAuLxOIsfZvLHlCyOJlRhjyOMKBHa.html
http://www.php.net/manual/ja/regexp.reference.onlyonce.php
http://www.php.net/manual/ja/regexp.reference.conditional.php
http://www.php.net/manual/ja/regexp.reference.comments.php
http://www.php.net/manual/ja/regexp.reference.recursive.php
http://www.php.net/manual/ja/regexp.reference.performance.php
#html{{
table border="0" cellpadding="5"><tr><td valign="top">
a href="http://www.amazon.co.jp/exec/obidos/ASIN/4839927073/sagasite-22/"><img src="" border="0"></a>
/td>
td valign="top">
a href="http://www.amazon.co.jp/exec/obidos/ASIN/4839927073/sagasite-22/">PHPマスターブック PHP5対応</a>
br>
坂田 健二<br>
毎日コミュニケーションズ<br>
2008-03-27<br>/td></tr></table>
}}
サンプルコードは、「preg_match」関数の使用例に変更しました。
「0~9の数字のいずれか」や「a~zの英小文字のいずれか」のように、いくつかの文字の中の1つにマッチすればいい場合には文字クラスを使用します。文字クラスでは[]内にマッチさせたい文字を記述します。
#code(php){{
?php
$target = '123abc';
$pattern = '/[0123456789][0123456789]/';
$result = preg_match($pattern, $target);
if ($result) {echo $target."には2桁の数字が含まれています。";} else {
echo $target."には2桁の数字が含まれていません。";}
}}
メタ文字 | 説明 |
\d | 数字の1文字を表す(文字クラス[0-9]と同じ) |
\D | 数字以外の1文字を表す(文字クラス[^0-9]と同じ) |
\w | 英数字、アンダースコアの1文字を表す(文字クラス[a-zA-Z_0-9]と同じ) |
\W | 英数字、アンダースコア以外の1文字を表す(文字クラス[^a-zA-Z_0-9]と同じ) |
\s | 空白文字(半角スペース、タブ、改行文字)を表す(文字クラス[\n\r\f\t]と同じ) |
\S | 空白文字(半角スペース、タブ、改行文字)以外を表す(文字クラス[^\n\r\f\t]と同じ) |
#code(php){{
?php
$target = '123abc';
$pattern = '/\d\d/';
$result = preg_match($pattern, $target);
if ($result) {echo $target."には2桁の数字が含まれています。";} else {
echo $target."には2桁の数字が含まれていません。";}
}}
パターンマッチで直前のパターン(文字)が何回繰り返すがを指定するには次表に示す量指示子や、「.」(ドット)を使って記述することができます。
(「.」は改行文字を除く任意の1文字を表すメタ文字です。)
量指示子 | 繰り返す回数 |
* | 0回以上繰り返す |
+ | 1回以上繰り返す |
? | 0回もしくは1回以上繰り返す |
{m} | m回繰り返す |
{m,} | m回以上繰り返す |
{m.n} | m回以上、n回以下繰り返す |
#code(php){{
?php
$target = 'body';
$pattern = '/b.+y/';
$result = preg_match($pattern, $target, $matches);
if ($result) {echo $target."は「b.+y」にマッチします"; var_dump($matches);} else {
echo $target."は「b.+y」にマッチしません";}
}}
パターンマッチでマッチさせる位置を指定するには次表に示す位置指示子を使用します。
「^」をパターンの先頭に記述した場合は、「行の先頭」という意味になりますが、パターンの先頭以外に「^」を記述すると文字の「^」として扱われます(文字クラスの先頭に記述すると「^」は否定の意味になります)。
パターンの先頭で「^」を文字の「^」として認識させるには「\^」と記述してください。
また同様にパターンの最後の文字の「$」を記述するには「\$」としてください。
位置指示子 | 指定位置 |
^ | 行の先頭 |
$ | 行の末尾 |
\A | 文字列の先頭 |
\Z | 文字列の末尾 |
\b | 単語区切り |
\B | 単語区切り以外 |
例えば、「a」から始まって「b」で終わるパターンは「^a.*b$」のように記述します。
#code(php){{
?php
$target = 'a123b';
$pattern = '/^a.*b$/';
$result = preg_match($pattern, $target);
if ($result) {echo $target."は「^a.*b$」にマッチします。";} else {
echo $target."は「^a.*b$」にマッチしません。";}
}}
「'abc'または'xyz'にマッチする」というようなor条件をパターンに記述したい場合には「|」を使用します。
「butterfly」または「butterflies」にマッチするというパターン
#code(php){{
?php
$target = 'Perfume butterfly';
$pattern = '/butterfl(y|ies)/';
$result = preg_match($pattern, $target);
if ($result) {echo $target."にはbutterflyもしくはbutterfliesが含まれています。";} else {
echo $target."にはbutterflyもしくはbutterfliesが含まれていません。";}
}}
() | パターンをグループ化する。 |
PHP正規表現チェッカー ver1.0.3
http://www.rider-n.sakura.ne.jp/regexp/regexp.php