web-dev-qa-db-ja.com

PHP文字列のUnicode文字

この質問は恥ずかしいほど単純に見えますが、答えを見つけることができませんでした。

次のC#コード行に相当するPHPとは何ですか?

string str = "\u1000";

このサンプルは、「Unicode数値」が16進数で1000(10進数で4096)である単一のUnicode文字を含む文字列を作成します。

つまり、PHPで、「Unicode数値」が知られている単一のUnicode文字を含む文字列を作成するにはどうすればよいですか?

139
Telaclavo

JSONは\uxxxx構文を直接サポートしているため、最初に思い浮かぶのは次のとおりです。

$unicodeChar = '\u1000';
echo json_decode('"'.$unicodeChar.'"');

別のオプションは、mb_convert_encoding()を使用することです

echo mb_convert_encoding('က', 'UTF-8', 'HTML-ENTITIES');

または、UTF-16BE(ビッグエンディアン)とUnicodeコードポイント間の直接マッピングを利用します。

echo mb_convert_encoding("\x10\x00", 'UTF-8', 'UTF-16BE');
162
Stefan Gehrig

PHP 7.0.0では "Unicodeコードポイントエスケープ"構文 が導入されました。

関数を呼び出さずに 二重引用符 または heredoc 文字列を使用して、Unicode文字を簡単に書くことができるようになりました。

$unicodeChar = "\u{1000}";
117
Blackhole

PHPは、これらのUnicodeエスケープシーケンスを認識しません。ただし、未知のエスケープシーケンスは影響を受けないため、このようなUnicodeエスケープシーケンスを変換する独自の関数を作成できます。

function unicodeString($str, $encoding=null) {
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/u', create_function('$match', 'return mb_convert_encoding(pack("H*", $match[1]), '.var_export($encoding, true).', "UTF-16BE");'), $str);
}

または create_function の代わりに 匿名関数式 で:

function unicodeString($str, $encoding=null) {
    if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
    return preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/u', function($match) use ($encoding) {
        return mb_convert_encoding(pack('H*', $match[1]), $encoding, 'UTF-16BE');
    }, $str);
}

その使用法:

$str = unicodeString("\u1000");
19
Gumbo

誰もまだこれについて言及していないのはなぜかと思いますが、 二重引用符で囲まれた文字列 のエスケープシーケンスを使用して、ほぼ同等のバージョンを実行できます。

\x[0-9A-Fa-f]{1,2}

正規表現に一致する文字のシーケンスは、16進表記の文字です。

ASCIIの例:

<?php
    echo("\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21");
?>

"こんにちは世界"

したがって、あなたの場合、あなたがする必要があるのは$str = "\x30\xA2";だけです。ただし、これらは文字ではなくbytesです。 Unicodeコードポイントのバイト表現はUTF-16ビッグエンディアンと一致するため、次のように直接出力できます。

<?php
    header('content-type:text/html;charset=utf-16be');
    echo("\x30\xA2");
?>

別のエンコーディングを使用している場合は、それに応じてバイトを変更する必要があります(ほとんどの場合、手作業でも可能ですが、ライブラリで行われます)。

UTF-16リトルエンディアンの例:

<?php
    header('content-type:text/html;charset=utf-16le');
    echo("\xA2\x30");
?>

UTF-8の例:

<?php
    header('content-type:text/html;charset=utf-8');
    echo("\xE3\x82\xA2");
?>

pack 関数もありますが、遅いと思われます。

19
Pacerier
html_entity_decode('&#x30a8;', 0, 'UTF-8');

これも機能します。ただし、json_decode()ソリューションははるかに高速です(約50倍)。

7
flori

試してください Portable UTF-8

$str = utf8_chr( 0x1000 );
$str = utf8_chr( '\u1000' );
$str = utf8_chr( 4096 );

すべて同じように機能します。 utf8_ord()で文字のコードポイントを取得できます。 ポータブルUTF-8についての詳細を読む

7
Hamid Sarfraz

他の人が述べたように、PHP 7は\u Unicode構文のサポートを直接導入します。

他の人にも言及されているように、PHPの賢明なUnicode文字の記述から文字列値を取得する唯一の方法は、それを他のもの(たとえば、JSON解析、HTML解析、または他の形式)から変換することです。しかし、これには実行時のパフォーマンスコストがかかります。

ただし、もう1つのオプションがあります。 \xバイナリエスケープを使用して、PHPで文字を直接エンコードできます。 \xエスケープ構文もPHP 5でサポートです。

これは、自然な形で文字列に文字を直接入力したくない場合に特に便利です。たとえば、非表示の制御文字である場合、またはその他の空白を検出するのが難しい場合。

まず、証明の例:

// Unicode Character 'HAIR SPACE' (U+200A)
$htmlEntityChar = "&#8202;";
$realChar = html_entity_decode($htmlEntityChar);
$phpChar = "\xE2\x80\x8A";
echo 'Proof: ';
var_dump($realChar === $phpChar); // bool(true)

別の回答でPacerierが言及したように、このバイナリコードは特定の文字エンコーディングに固有であることに注意してください。上記の例では、\xE2\x80\x8AはUTF-8のU + 200Aのバイナリコーディングです。

次の質問は、U+200Aから\xE2\x80\x8Aにどのように行きますか?

以下は、JSON文字列、HTMLエンティティ、またはネイティブ文字列として取得した他のメソッドに基づいて、任意の文字のエスケープシーケンスを生成するPHPスクリプトです。

function str_encode_utf8binary($str) {
    /** @author Krinkle 2018 */
    $output = '';
    foreach (str_split($str) as $octet) {
        $ordInt = ord($octet);
        // Convert from int (base 10) to hex (base 16), for PHP \x syntax
        $ordHex = base_convert($ordInt, 10, 16);
        $output .= '\x' . $ordHex;
    }
    return $output;
}

function str_convert_html_to_utf8binary($str) {
    return str_encode_utf8binary(html_entity_decode($str));
}
function str_convert_json_to_utf8binary($str) {
    return str_encode_utf8binary(json_decode($str));
}

// Example for raw string: Unicode Character 'INFINITY' (U+221E)
echo str_encode_utf8binary('∞') . "\n";
// \xe2\x88\x9e

// Example for HTML: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_html_to_utf8binary('&#8202;') . "\n";
// \xe2\x80\x8a

// Example for JSON: Unicode Character 'HAIR SPACE' (U+200A)
echo str_convert_json_to_utf8binary('"\u200a"') . "\n";
// \xe2\x80\x8a
1
Timo Tijhof