この広告は、90日以上更新していないブログに表示しています。
できるだけ正確な記述を目指していますが、誤りがありましたら、お知らせ願います。
(最終更新: 2013/3/29 11:22)
正規表現パターンは文字列として記述します。PHP には正規表現リテラルがありません。
ややこしいですが、パターンの文字列を echo して表示された結果が、正規表現エンジンに渡されるパターンになります。
$ cat test.php <?phpecho '/\\\\/', PHP_EOL;$ php test.php /\\/
pcre で日本語を処理する場合は、文字エンコーディングはUTF-8 にし、パターン修飾子 u を付ける必要があります。付けないとマルチバイト文字が適切に処理されず、意図した結果を得られない場合があります。
<?phpif(PHP_OS=== 'WIN32'||PHP_OS=== 'WINNT'){setlocale(LC_ALL, 'C');}else{if(setlocale(LC_ALL, 'ja_JP.UTF-8')===false){exit('Can\'t set locale to UTF-8');}}$str= 'aあc';var_dump(preg_match('/a.c/',$str));var_dump(preg_match('/a.c/u',$str));$str= 'いう';var_dump(preg_match('/あ?いう/',$str));var_dump(preg_match('/あ?いう/u',$str));
上記の結果は、以下のようになります。
int(0)int(1)int(0)int(1)
\w, \d, \s について確認してみましょう (PHP 5.3.21)。
まず、\w の全角の漢字、かな、英数。
<?phpif(PHP_OS=== 'WIN32'||PHP_OS=== 'WINNT'){setlocale(LC_ALL, 'C');}else{if(setlocale(LC_ALL, 'ja_JP.UTF-8')===false){exit('Can\'t set locale to UTF-8');}}mb_regex_encoding('UTF-8');var_dump(preg_match('/\w/u', '亜'));var_dump(mb_ereg('\w', '亜'));var_dump(preg_match('/\w/u', 'あ'));var_dump(mb_ereg('\w', 'あ'));var_dump(preg_match('/\w/u', 'ア'));var_dump(mb_ereg('\w', 'ア'));var_dump(preg_match('/\w/u', 'A'));// 全角のAvar_dump(mb_ereg('\w', 'A'));var_dump(preg_match('/\w/u', '1'));// 全角の1var_dump(mb_ereg('\w', '1'));
この結果は、以下のようになります。
int(1)int(1)int(1)int(1)int(1)int(1)int(1)int(1)int(1)int(1)
全角の記号。
<?phpif(PHP_OS=== 'WIN32'||PHP_OS=== 'WINNT'){setlocale(LC_ALL, 'C');}else{if(setlocale(LC_ALL, 'ja_JP.UTF-8')===false){exit('Can\'t set locale to UTF-8');}}mb_regex_encoding('UTF-8');var_dump(preg_match('/\w/u', ' '));// 全角スペースvar_dump(mb_ereg('\w', ' '));var_dump(preg_match('/\w/u', '!'));// 全角の感嘆符var_dump(mb_ereg('\w', '!'));var_dump(preg_match('/\w/u', '。'));var_dump(mb_ereg('\w', '。'));var_dump(preg_match('/\w/u', '_'));// 全角のアンダースコアvar_dump(mb_ereg('\w', '_'));
この結果は、以下のようになります。
int(0)bool(false)int(0)bool(false)int(0)bool(false)int(0)int(1)
全角のアンダースコアは、pcre では \w にマッチしませんが、mbregex ではマッチします。
半角カナ。
<?phpif(PHP_OS=== 'WIN32'||PHP_OS=== 'WINNT'){setlocale(LC_ALL, 'C');}else{if(setlocale(LC_ALL, 'ja_JP.UTF-8')===false){exit('Can\'t set locale to UTF-8');}}mb_regex_encoding('UTF-8');var_dump(preg_match('/\w/u', 'ア'));// 半角カナvar_dump(mb_ereg('\w', 'ア'));
この結果は、以下のようになります。
int(1)int(1)
次に \d です。
<?phpif(PHP_OS=== 'WIN32'||PHP_OS=== 'WINNT'){setlocale(LC_ALL, 'C');}else{if(setlocale(LC_ALL, 'ja_JP.UTF-8')===false){exit('Can\'t set locale to UTF-8');}}mb_regex_encoding('UTF-8');var_dump(preg_match('/\d/u', '1'));// 全角の1var_dump(mb_ereg('\d', '1'));var_dump(preg_match('/\d/u', '一'));// 漢数字の1var_dump(mb_ereg('\d', '一'));
この結果は、以下のようになります。
int(1)int(1)int(0)bool(false)
全角数字は \d にマッチしますが、漢数字はマッチしません。
最後に \s です。
<?phpif(PHP_OS=== 'WIN32'||PHP_OS=== 'WINNT'){setlocale(LC_ALL, 'C');}else{if(setlocale(LC_ALL, 'ja_JP.UTF-8')===false){exit('Can\'t set locale to UTF-8');}}mb_regex_encoding('UTF-8');var_dump(preg_match('/\s/u', ' '));// 全角スペースvar_dump(mb_ereg('\s', ' '));
この結果は、以下のようになります。
int(1)int(1)
続いて、mbregex での \w の文字エンコーディングの違いについてもみておきましょう。
<?php$provider=array(// 全角漢字、英数、ひらがな、カタカタ '亜', 'A', '1', 'あ', 'ア',// 全角記号 '!', '_',// 全角スペース ' ',// 半角カナ 'ア',);echo 'mbregex: UTF-8 SJIS EUC-JP'. PHP_EOL;foreach($provideras$str){echo$str. ':';mb_regex_encoding('UTF-8');$test=mb_ereg('\w',$str);if($test===false)$test= '0';echo$test. '';mb_regex_encoding('SJIS');$str_s=mb_convert_encoding($str, 'SJIS', 'UTF-8');$test=mb_ereg('\w',$str_s);if($test===false)$test= '0';echo$test. '';mb_regex_encoding('EUC-JP');$str_e=mb_convert_encoding($str, 'EUC-JP', 'UTF-8');$test=mb_ereg('\w',$str_e);if($test===false)$test= '0';echo$test. '';echo PHP_EOL;}
この結果は、以下のようになります。
mbregex: UTF-8 SJIS EUC-JP亜: 1 1 1 A: 1 1 1 1: 1 1 1 あ: 1 1 1 ア: 1 1 1 !: 0 1 1 _: 1 1 1 : 0 1 1 ア: 1 0 1
SJIS とEUC-JP では、全角記号も \w にマッチします。半角カナはSJIS では \w にマッチしません。
\d はどうでしょうか?
<?php$provider=array(// 全角漢字、英数、ひらがな、カタカタ '亜', 'A', '1', 'あ', 'ア',// 全角記号 '!', '_',// 全角スペース ' ',// 半角カナ 'ア',);echo 'mbregex: UTF-8 SJIS EUC-JP'. PHP_EOL;foreach($provideras$str){echo$str. ':';mb_regex_encoding('UTF-8');$test=mb_ereg('\d',$str);if($test===false)$test= '0';echo$test. '';mb_regex_encoding('SJIS');$str_s=mb_convert_encoding($str, 'SJIS', 'UTF-8');$test=mb_ereg('\d',$str_s);if($test===false)$test= '0';echo$test. '';mb_regex_encoding('EUC-JP');$str_e=mb_convert_encoding($str, 'EUC-JP', 'UTF-8');$test=mb_ereg('\d',$str_e);if($test===false)$test= '0';echo$test. '';echo PHP_EOL;}
この結果は、以下のようになります。
mbregex: UTF-8 SJIS EUC-JP亜: 0 0 0 A: 0 0 0 1: 1 0 0 あ: 0 0 0 ア: 0 0 0 !: 0 0 0 _: 0 0 0 : 0 0 0 ア: 0 0 0
\d の場合は、全角数字はUTF-8 でしかマッチしません。
setlocale() でロケールを設定します。
<?phpif(setlocale(LC_ALL, 'ja_JP.UTF-8')===false){exit('Can\'t set locale to UTF-8');}
Windows ではロケールをUTF-8 にする方法がないようなので、どうするのが正しいのかはわかりません。知ってる人がいましたら、お教え願いたいです。
pcre では、UTF-8 の場合は、'/abc/u' のように必ず「u」を指定します。
mbregex では、mb_regex_encoding() で文字エンコーディングを指定し、必要があれば mb_regex_set_options() でオプションを変更します。
例えば、半角数字を期待するなら \d ではなく [0-9] を使います。
最後に、正常系、異常系についてユニットテストを書いておきます。そうすれば、自分の思い違い、正規表現エンジンの違いによる微妙な違い、万一PHP の仕様が突然変わった場合も発見できます。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。