2010.03.18
PHPの正規表現で注意したい5つのこと
他言語をメインでやっている方が、
PHPで正規表現を扱う際に気を付けたいことをまとめました。
1. preg系で日本語を扱うにはu修飾子
2. preg_match_all の戻り値
3. preg_match_all の検索結果
4. “/” で括る必要は無い
5. 後方参照は $1 で取る
PHPで正規表現を扱う際に気を付けたいことをまとめました。
1. preg系で日本語を扱うにはu修飾子
2. preg_match_all の戻り値
3. preg_match_all の検索結果
4. “/” で括る必要は無い
5. 後方参照は $1 で取る
1. preg系で日本語を扱うにはu修飾子
preg系は、そのままだと日本語を正確に扱えないので、u修飾子の指定が必要
# 非マッチ
$result = preg_match('/は.ほ/', 'いろはにほへと');
var_dump($result); // -> 0
# マッチ
# u修飾子が「文字列をUTF-8として扱う」フラグ
$result = preg_match('/は.ほ/u', 'いろはにほへと');
var_dump($result); // -> 1
# これはマッチ
$result = preg_match('/はにほ/', 'いろはにほへと');
var_dump($result); // -> 1 ... 単にバイナリで見てるからだと思う(推測)
他の文字コードについては、どうするかは未調査です・・・。
2. preg_match_all の戻り値
検索結果オブジェクトではなく、boolean でもありません。
何かというと int で、0以上の「全体一致した回数」が返されます。
何かというと int で、0以上の「全体一致した回数」が返されます。
$subject = 'きょうとうきょうとうきょう'; $pattern = '/きょうと/u'; $matches = array(); $result = preg_match_all($pattern, $subject, $matches); var_dump($result); // -> 2
3. preg_match_all の検索結果
検索結果オブジェクトが無いので、どこに結果が入るんだろう? というと、
参照(シンボル)渡しをしている第3引数に配列として結果群が格納されています。
参照(シンボル)渡しをしている第3引数に配列として結果群が格納されています。
$subject = 'ABCDEF'; $pattern = '/A(B)(C)|D(E)F/'; $matches = array(); $result = preg_match_all($pattern, $subject, $matches); var_dump($matches);
↓検索結果の出力結果
# $matches[0] は、全体一致
# $matches[1] は、1個目の部分一致
# $matches[2] は、2個目の部分一致
# … という具合に対応している。
# 部分一致の2階層目の値は、全体一致のどちらに属するかに対応
# “B” “C” は “ABC” 側だから [0] に格納されていて、”E” はその逆
array(4) {
[0]=>
array(2) {
[0]=>
string(3) “ABC”
[1]=>
string(3) “DEF”
}
[1]=>
array(2) {
[0]=>
string(1) “B”
[1]=>
string(0) “”
}
[2]=>
array(2) {
[0]=>
string(1) “C”
[1]=>
string(0) “”
}
[3]=>
array(2) {
[0]=>
string(0) “”
[1]=>
string(1) “E”
}
}
中々の複雑さです。
4. “/” で括る必要は無い
先程の例から、パターン文字列を “/” で括っていますが、
これは一部の文字を除いて、何でも構いません。
これは一部の文字を除いて、何でも構いません。
# ◎ 良く見かける '/string/'; '#string#'; # ○ 問題ない ';string;'; '_string_'; '=string='; # × エラー、半角英数と"\"等、一部はダメ 'astringa'; '0string0'; # △ エラーにはならないが、内部でメタ文字として使えなくなるので非推奨 '^string^'; '$string$';
なお、括弧に使われている文字を内部で文字列として使う場合は、
“\” でエスケープします。
5. 後方参照は $1 で取る
“\1″ で表現する言語が多いので念のため
$result = preg_replace('#(\d+)/(\d+)#', '$1月$2日', '3/4');
var_dump($result); // -> "3月4日"
PHPは文字列に “$foo” で変数を埋め込めるので、ちょっとややこしいすね。
Trackback URL
Comment & Trackback
Comment feed
Comment