👌

【PHP】文字列をバイト列やユニコードのエスケープシーケンスに変換する

2023/07/10に公開

テストコードを書くとき、目に見えない文字やシステムにフォントがインストールされていない文字を書くために、バイト列やユニコードのエスケープシーケンスを使うことがよくあります。コピペで使えるように標準関数にしてもよさそうに思えますが、意外とよい名前がないために標準化ができていないのかもしれません。

test.php
// https://www.php.net/manual/en/function.bin2hex.php#47663
function encode_hex(string $str): string
{
    return '\\x'.substr(chunk_split(bin2hex($str), 2, '\\x'), 0, -2);
}

function encode_uni(string $str): string
{
    return preg_replace_callback(
        '/\X/us', 
        fn($matches) => '\\u{'.dechex(mb_ord($matches[0])).'}',
        $str);
}
test.php
$str = "あいう";

var_dump(
    encode_hex($str),
    '\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86' === encode_hex($str),
    encode_uni($str),
    '\u{3042}\u{3044}\u{3046}' === encode_uni($str)
);

バイト列表記への変換は preg_replace_callback 関数でも可能である。

test.php
function encode_hex2(string $str): string
{
    return preg_replace_callback(
        '/./s',
        fn($matches) => '\\x'.bin2hex($matches[0]),
        $str);
}

ベンチマークをとると preg_replace_callback 関数のほうが遅かった。

encode_hex
52709400
encode_hex2
414942300
test.php
$str = "あいうえお";

$timer = timer([
    'encode_hex' => function() use($str) { encode_hex($str); },
    'encode_hex2' => function() use($str) { encode_hex2($str); }
]);

foreach ($timer as $message => $time) {
    echo $message, PHP_EOL, $time, PHP_EOL;
}
function timer(array $callables, int $repeat = 100000): array
{

    $ret = [];
    $save = $repeat;

    foreach ($callables as $key => $callable) {

        $start = hrtime(true);

        do {      
            $callable();
        } while($repeat -= 1);

        $stop = hrtime(true);
        $ret[$key] = $stop - $start;
        $repeat = $save;
    }

    return $ret;
}

Discussion