郵便番号

mb_innternal_encoding="EUC-JP"な環境で
郵便番号の数値以外を排除しようとして小一時間はまる。

現象

print_r( trim( mb_ereg_replace('[^0-9]','','〒855-1234') ) );

とすると下記のようになる。

551234

期待値としては『8551234』のようになってもらいたかったんだが、
何故か『〒』と一緒にその次の数値も置換されて消えてしまう・・・


で、小一時間ほどあーだこーだと試した結果、たどり着いたのがコレ↓

mb_regex_encoding('UTF-8');
print_r( trim( mb_ereg_replace('[^0-9]','','〒855-1234') ) );

こうすると下記のように、期待した結果を得ることができた。

8551234

要はmb_regex_encoding関数を用いて正規表現関数の使用する文字コードUTF-8に変更しただけ。
なぜUTF-8ならOKでEUC-JPならNGなのか、詳しいことは知らないが、一部記号や特殊文字を扱う際に問題があるのだろう。
これからはマルチバイト文字の正規表現を使う場合、UTF-8で処理するようにしよう。

(2006/12/01追記)
ちょっと違った。
上記のようにすると、環境によっては↓のエラーになる。

Warning: mb_ereg_replace() [function.mb-ereg-replace]: mbregex compile err: premature end of regular expression in [エラーの場所]

どうも正規表現のパラメータ*1コンパイルエラーが発生していると言いたいみたい。

ちょっと考えてみるとエラーになるのは当然だ。
mb_regex_encodingで指定された文字コードを使用して、mb関数は文字列を処理する。
もしmb_regex_encodingで指定された文字コードと、その環境のPHPが使用している内部処理用の文字コードが違った場合、どこかの時点で問題が発生するということだ。

要はmbstring.internal_encodingで指定されている文字コードのを設定すれば良いみたい。

なので↓のように、なんでもかんでもUTF-8で処理しようとするのではなく

mb_regex_encoding('UTF-8');

↓のように、環境に合わせた文字コードを指定してやるほうが良さそう。

mb_regex_encoding(mb_internal_encoding())

*1:この場合はmb-ereg-replaceの第1引数