hnwの日記

mb_ereg系の関数でUTF-16を扱う方法

PHPでmb_regex_encoding("UTF-16")すると、一見mb_ereg系関数が期待通りに動きません。

<?php

$whitespace_regex = '^\s+$';
$uft16_whitespace = "\x00\x20\x30\x00\x00\xa0";
mb_regex_encoding("UTF-16");
var_dump(mb_ereg_match($whitespace_regex, $uft16_whitespace)); // false


試行錯誤の結果、動かす方法を見つけました。

<?php

$whitespace_regex = mb_convert_encoding('^\s+$', "UTF-16", "ASCII");
$uft16_whitespace = "\x00\x20\x30\x00\x00\xa0";
mb_regex_encoding("UTF-16");
var_dump(mb_ereg_match($whitespace_regex, $uft16_whitespace)); // true


mb_regex_encodingは、マッチ対象文字列と正規表現文字列と両方のエンコーディングを指定する関数のようです。ちょっとビックリですね。


マッチ対象文字列のエンコーディングを変換した方がマシなんじゃね?と思わないでもないです。



わかりにくい気がしたので補足:本文最後の「マシなんじゃ」は、UTF-16の文字を検査したい場合、PHP側で文字列をUTF-8に変換してから検査した方が正規表現が見やすくていいんじゃ?という意味です。U+3000にマッチさせたい場合の正規表現で'\x{3000}'とは書けず、"\x00\x5c\x00x\x00{\x003\x000\x000\x000\x00}"になるのはさすがに読みにくいと思うんです。この例に関して言えば"\x30\x00"という書き方もできるわけですから、一長一短ですかね…。