« 公開鍵、秘密鍵ってなに? | はじめてのシェルスクリプト »

2010.03.18

PHPの正規表現で注意したい5つのこと

このエントリをはてなブックマークに追加このエントリをdel.icio.usに追加このエントリをLivedoor Clipに追加このエントリをYahoo!ブックマークに追加このエントリをPOOKMARK. Airlinesに追加このエントリをBuzzurl(バザール)に追加このエントリをnewsingに追加
他言語をメインでやっている方が、
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 ... 単にバイナリで見てるからだと思う(推測)

他の文字コードについては、どうするかは未調査です・・・。

» PHPマニュアル: パターン修飾子

 

2. preg_match_all の戻り値

検索結果オブジェクトではなく、boolean でもありません。
何かというと int で、0以上の「全体一致した回数」が返されます。

$subject = 'きょうとうきょうとうきょう';
$pattern = '/きょうと/u';
$matches = array();
$result = preg_match_all($pattern, $subject, $matches);
var_dump($result); // -> 2

 

3. preg_match_all の検索結果

検索結果オブジェクトが無いので、どこに結果が入るんだろう? というと、
参照(シンボル)渡しをしている第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” で変数を埋め込めるので、ちょっとややこしいすね。

 

以上

いかがでしたでしょうか?
 
善き /P(HP)+/ ライフをお過ごしいただければ、幸いです!
 
» PHPマニュアル: 正規表現 (Perl 互換)

Trackback URL

Comment & Trackback

No comments.

Comment feed

Comment





XHTML: You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>