BLOG ENTRY

マルチバイト文字Unicodeで正規表現preg_match()[PHP]

php

確証はないけどPHPの正規表現でおもしろいことを発見してしまった。
EUC-JPのunicode下二桁がF5~FEの文字はpreg_match()がマッチしないっぽい。

例えば、サーバ文字コードはEUC-JPで、

<?php
function chkString($str) {
    $pattern = "/^[亜-熙]*$/";
    if (preg_match($pattern, $str) > 0) {
        return true;
    }
    return false;
}
$str = "歯";
$result = chkString($str);

trueが返ってきそうなもんだがfalseが返ってきてくれます。

正規表現のパターン箇所をこんな感じに変えても同じく。

$pattern = "^[\xA1\xA0-\xF4\xF6]*$";

この文字に限らず、EUC-JPunicode下二桁がF5~FEの文字だと同じようにスカってしまいます。。。

なので、こんなコードを書いてみた。
かなり体育会系で汗くさいコードですが、一応意図した動作をしてくれた。

<?php
function chkString($str) {
    $start16    = "A1A0";
    $end16      = "F4A6";
    $start10    = hexdec($start16);
    $end10      = hexdec($end16);

    for ($i = 0; $i < mb_strlen($str); $i++) {
        $char        = mb_substr($str, $i, 1);
        $charUnicode = bin2hex($char);
        $char10      = hexdec($charUnicode);
        if ($char10 < $start10 || $char10 > $end10) {
            return false;
        }
    }
    return true;
}
$str = "歯";
$result = chkString($str);

まず比較対象の16進数Unicodeを10進数に変換して、対象文字数分ループしながら
1文字ずつ、判別文字列をUnicode16進数に変換して10進数に変換して比較。

preg_matchは意図した通りに動かなかったので、
他の正規表現関数も同じかなと決め込んでたけどmb_ereg()を使えば意図した動作をしてくれた。

<?php
function chkString($str) {
    $pattern = "^[\xA1\xA0-\xF4\xF6]*$";
    if (mb_ereg($pattern, $str) > 0) {
        return true;
    }
    return false;
}
$str = "歯";
$result = chkString($str);

これは$resultにちゃんとtrueが返ってきました。

preg_match・・・不思議だ。。

No related posts.

WRITE COMMENT


(required)


(required)


(required)

MENU

veltica creative of twitter