マルチバイト対応正規表現ライブラリの検証

2007.08.03 Author: Jas

今日はPHPのマルチバイト対応正規表現ライブラリの検証レポート(UTF-8)です。

文字列の先頭と末尾の空文字を取り除く関数として、trim()がありますが、この関数はマルチバイトに対応していないため、全角スペースにも対応したmb_trim()を作成しようとしていました。

全角スペースについては、mb_ereg_replace()を使い、正規表現で除去しようとしていたのですが、スクリプトを書いてテストしてみるとなぜかうまくいきません。文字コードの指定もしてみたのですが、それでもうまくいきません。

いろいろ試したり、調べたりしていると、これはPHP4のマルチバイト対応正規表現ライブラリにバグがあるのではないかという疑いが出てきたので検証してみました。

[目的]
PHP4と5でのマルチバイト対応正規表現の比較

[環境]
PHP Ver.4.3.9 及び Ver.5.1.6
開発言語 UTF-8

[検証方法]


// 変換前文字列
$str = "   あ  い  う   ";

// 最初に作った正規表現
$pattern = "^ *([^ ]*.*[^ ]+)* *$|^ +$";
echo mb_ereg_replace($pattern, "\\1", $str);

// 全角スペースを()で囲ったもの
$pattern = "^( )*([^( )]*.*[^( )]+)*( )*$|^ +$";
echo mb_ereg_replace($pattern, "\\2", $str);

以上2つの置換をmb_regex_encoding()を指定しない場合とmb_regex_encoding("UTF-8")に指定した場合について、PHP4と5でそれぞれ試してみました。(空白部分は全て全角スペース)
期待する結果は、いずれも先頭と末尾の全角スペースを除去した「あ  い  う」です。

[結果]
1. PHP4の場合
- 正規表現文字コードを指定してない場合
(1) 「   あ  い  う   」
(2) 「あ  い  う」

- 正規表現文字コードをUTF-8に指定した場合
(3) 「あ  い  う   」
(4) 「あ  い  う   」

2. PHP5の場合
- 正規表現文字コードを指定してない場合
(5) 「   あ  い  う   」
(6) 「あ  い  う」

- 正規表現文字コードをUTF-8に指定した場合
(7) 「あ  い  う」
(8) 「あ  い  う」

[結論]
- 正規表現の文字コードを指定しない場合
→PHP4と5で同じ結果が得られた。
・文字コードの誤認識が起きているようでうまく置換されない・・・(1)(5)
・全角スペースを()で囲うと()の中がひと塊りと認識され、期待した結果が得られた・・・(2)(6)

- 正規表現文字コードをUTF-8に指定した場合
→PHP4でうまくいかなかった。
・PHP5では文字コードが正しく認識され、()がなくても期待した結果が得られた・・・(7)(8)
・PHP4では末尾全角スペースが除去されなかった・・・(3)(4)

どうやら、PHP4では正規表現の文字コードを指定しても全角スペースが1文字と認識されず(?)正規表現による置換がうまく動作しないようです。PHP5ではマルチバイト対応正規表現のアップデートがされているようなので、今回の不具合も修正されたようですね。

最後に。。。
今回の検証ではmb_ereg_replace()で全角スペースの置換をしましたが、UTF-8であればPerl 互換の正規表現の修飾子(u)を使えば、preg_replace()で全角スペースを()で囲うことなく置換できます。

名古屋のWebシステム開発・ネットワーク構築会社 コネクティボへ