こんにちはみなさん
へんてこな挙動に見舞われてキョドったので、その記念に記事書いちゃいます。
何が起こったのか
文書の校正を自動でやるツールをPHP作っている最中、表記ゆれのようなものがあったら、正しいものに書き換える、みたいなものを作っていました。
そのとき、正規表現を置換するのですが、次のような状態になりました。
$ php -a
php > $state = 'あああ';
php > echo preg_replace('/[あ]/', 'o', $state);
ooooooooo
おかしいな、3文字しか置換していないので、9文字に増えてしまったぞ???
ちなみに、
php > $state = 'あああ';
php > echo preg_replace('/あ/', 'o', $state);
ooo
php > $state = 'あああ';
php > echo preg_replace('/(あ|い)/', 'o', $state);
ooo
php > $state = '111';
php > echo preg_replace('/[1]/', 'o', $state);
ooo
となっていて、UTF-8のマルチバイト文字を文字セットで置換したときのみ、このような事象が発生する模様です。
また、この置換の際に文字化けも発生しているようで、判定外の文字が化けたりしました。
php > $state = 'あいうえお';
php > echo preg_replace('/[あう]/', 'え', $state);
えええええ�えええええ�ええ�
もうなにがなんだか。
どうすればいいのか
超単純な話をすれば、問題はマルチバイト文字をちゃんと扱えていないから、だと思われるので、uフラグをつければいいだけですね。
php > $state = 'あいうえお';
php > echo preg_replace('/[あう]/u', 'え', $state);
えいええお
それはいいのですが、なんで普通の置換 preg_replace('/あ/', 'o', $state);
は普通に動くのに、文字セットを使った場合にバグるのか。。。
というわけで、日本語を使いそうな場合はuフラグを付けたほうがいいみたいな話...になるのでしょうかね?
多分、文字コードの問題なんだろうなぁと思いつつ、そこまで詳しく確かめる気にもならないので、今回はこのへんで失礼します。