2006年10月28日

[PHP] mb_ereg()じゃない、preg_match_all()に/uをつけるんだ!

ウノウラボ Unoh Labs: PHPのちょっとしたコツ

 最近のスクリプト言語は機能が多く、基本的な機能はほとんど実装されているので、アルゴリズムをどうこうするより、どの機能を使うか選ぶ方が重要だったりしますね(コーディングの効率的にも)。

 自分にもそういったレベルで気をつけていることがいくつかあります。

-[早起き生活]PHPのパフォーマンスチューニング
-[早起き生活]PHPのパフォーマンスチューニング その2:count()も使い過ぎると重くなる
-[早起き生活]PHPのパフォーマンスチューニング その3:APC投入

 あと、最近気づいたTIPSとしては、

日本語を正規表現検索したいときでもereg系の関数を使うのはやめとけ

なんてのもあります。

 PHPの組み込み正規表現関数にはPHP独自のereg系とPerl互換のpreg系がありますが、ヘルプに書いてあるとおり、ereg系の関数は出来があんまり良くありません。

注意: Perl 互換の正規表現構文を使用する preg_match() のほうが、多くの場合 ereg() よりも速く動作します。
PHPマニュアル:eregより

 なので、できる限りpreg系の関数を使いたいわけですが、検索対象や検索パターンに日本語が含まれているときは、日本語処理に対応したereg系の関数であるmb_ereg系の関数が使われることが多いようです。

 しかし、このmb_ereg系の関数もあんまり出来がよろしくなくて、たとえば、次のURLで紹介されているサンプルコードでは、「上」や「一」といった漢字がスルーされてしまいます。

「すべての漢字を取り出す正規表現」をPHPで試す

 どうも、mb_ereg系の関数では、UTF-8をうまく扱えないようです。

 では、PHPでUTF-8の正規表現を扱うには、正規表現検索処理を自作するか、EUC-JPといった別の文字コードに変換してからmb_ereg系の関数で処理するしかないのでしょうか?

 実は、preg系の正規表現にパターン修飾子「u」を指定すると、パターン文字列がUTF-8でエンコードされた文字列として扱われるようになります(古いPHPマニュアルにPCRE_UTF8でパターン文字列がShift-JISエンコードされた文字列として処理されるとか書いてあるのはおそらく間違い)。

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

 先ほどの「上」や「一」をスルーしてしまうサンプルを、preg系の関数で書き直すと次のようになるでしょうか。

preg_match_all('/[一-龠]+|[ぁ-ん]+|[ァ-ヴー]+|[a-zA-Z0-9]+|[a-zA-Z0-9]+/u', $strToSplit, $aMatches);

 PHPの日本語正規表現処理まわりには、まだまだいろいろなトリビアがありそうな気がします。ほかにもあれば、教えてください。

posted by momose at 01:08 | Comment(5) | TrackBack(1) | 技術TIPS/まとめ | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
preg で UTF-8 を正しく扱えるかどうかは組み込まれている PCRE のバージョンに依存しますね。以前調べた結果は http://aligach.net/diary/20041228.html#p01 に挙げてありますのでご参考まで。5.x 系は調べてないんですけど、mb_* 系も鬼車になるとそれなりに性能がよくなるとか。
Posted by wtnabe at 2006年11月14日 11:35
こんばんは。

 ひとまず、4系でも、新しいバージョンを使っていれば大丈夫そうということですよね。
 鬼車についてははじめて知りました。Rubyにも使われている正規表現ライブラリなんですね。日本人が作っているようなので、マルチバイトへの対応についてもかなり期待できそうです。
Posted by momose at 2006年11月14日 23:12
「いすゞ」
はスルーしますね。

正確にはこちら
http://pentan.info/php/reg/is_hira.html
Posted by at 2009年01月08日 15:26
ぺさんこんばんは。

> 「いすゞ」
> はスルーしますね。

 「ゞ」はひらがななんですね。
 カタカナは、[ァ-ヾー]でしょうか?

Posted by momose at 2009年01月08日 21:14
http://pentan.info/php/reg/is_kana.html

UTFでは『ー』は、『ァ』から『ヾ』の間にあるので[ァ-ヾー]ではなくて[ァ-ヾ]です。
Posted by at 2009年01月23日 04:57
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.seesaa.jp/tb/26300967

この記事へのトラックバック

CodeIgniter | URIで日本語を使うのだ
Excerpt: デフォルトでhttp://example.com/hoge/こんにちは 「こんにちは」をurldecodeしたものをと投げかけると、「The URI you submitted has disallo...
Weblog: price-change:blog
Tracked: 2007-10-19 13:21