Символ Unicode в строке PHP


164

Этот вопрос выглядит смущающе простым, но я не смог найти ответ.

Что такое PHP эквивалент следующей строки кода C #?

string str = "\u1000";

В этом примере создается строка с одним символом Unicode, чье «числовое значение Unicode» равно 1000 в шестнадцатеричном формате (4096 в десятичном виде).

То есть в PHP как я могу создать строку с одним символом Unicode, чье «числовое значение Unicode» известно?



4
@diEcho: это только для сопоставления символов Юникода, но ОП хочет создать для этих символов.
— Стефан Гериг


Ответы:


178

Поскольку JSON напрямую поддерживает \uxxxxсинтаксис, первое, что приходит мне в голову:

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

Другой вариант будет использовать mb_convert_encoding()

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

или используйте прямое отображение между UTF-16BE (big endian) и кодовой точкой Unicode:

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

9
JSON - это не JavaScript.
— Гамбо

4
@ Гамбо: я знаю это, но здесь нет никакой разницы. Javascript и JSON поддерживают \uxxxxсинтаксис Unicode, поэтому вы можете использовать его json_decodeдля работы с искусственно созданным строковым представлением JSON. Я изменил формулировку, чтобы уточнить это.
— Стефан Гериг

3
Итак, строгая формулировка одного ответа на мой вопрос: $ str = json_decode ('"\ u1000"'); Спасибо.
— Телаклаво

Я пытался, echo json_decode('\u201B');Который ссылается на одну возвращенную кавычку. Однако это не работает, то есть не выводит (даже если hd
— отправлено

4
Вам нужно echo json_decode('"\u201B"');. Двойные кавычки вокруг символа Unicode являются обязательными.
— Стефан Гериг

162

В PHP 7.0.0 введен синтаксис «Unicode codepoint escape» .

Теперь можно легко писать символы Юникода, используя двойные кавычки или строку heredoc , без вызова какой-либо функции.

$unicodeChar = "\u{1000}";

Это можно использовать так: wordwrap($longLongText, 20, "\u{200B}", true);( пробел нулевой ширины )
— sanmai

5
Я считаю, что ОП хотел этот ответ, а не принятый ответ. Во всяком случае, когда я искал "Unicode в PHP", это было потому, что я хотел этот ответ, а не принятый ответ. Возможно, "\ u {abcd}" не существовало, когда этот вопрос был впервые задан. Если так, то принятый ответ должен быть перенесен.
— Адам Чалкрафт

23

Интересно, почему никто еще не упомянул об этом, но вы можете сделать почти эквивалентную версию, используя escape-последовательности в двойных кавычках :

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

Последовательность символов, соответствующая регулярному выражению, является символом в шестнадцатеричной записи.

Пример ASCII:

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

Привет мир!

Так что для вашего случая все, что вам нужно сделать, это $str = "\x30\xA2";. Но это байты , а не символы. Байтное представление кодовой точки 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функция, но вы можете ожидать, что она будет медленной.


Идеально подходит для случаев, когда копирование / вставка символа маркера (\ xE2 \ x80 \ xA2) может привести к ошибке кодирования UTF-8 в исходном документе. Спасибо.
— Jimp

21

PHP не знает этих escape-последовательностей Unicode. Но поскольку неизвестные escape-последовательности остаются неизменными, вы можете написать свою собственную функцию, которая преобразует такие escape-последовательности 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");

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

Это тоже работает. Однако решение json_decode () намного быстрее (примерно в 50 раз).


Простой, элегантный, простой и абсолютно безопасный метод. +10
— andreszs


3

Как уже упоминалось, PHP 7 \uнапрямую поддерживает синтаксис Unicode.

Как также упоминалось другими, единственный способ получить строковое значение из любого разумного описания символов Unicode в PHP, это преобразовать его из чего-то еще (например, JSON-разбор, HTML-разбор или некоторая другая форма). Но это происходит за счет производительности во время выполнения.

Однако есть еще один вариант. Вы можете закодировать символ непосредственно в PHP с \xдвоичным экранированием. \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это двоичное кодирование для U + 200A в UTF-8.

Следующий вопрос, как вы добираетесь U+200Aдо \xE2\x80\x8A?

Ниже приведен PHP-скрипт для генерации escape-последовательности для любого символа на основе либо строки JSON, HTML-сущности, либо любого другого метода, если у вас есть его как собственная строка.

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

0
function unicode_to_textstring($str){

    $rawstr = pack('H*', $str);

    $newstr =  iconv('UTF-16BE', 'UTF-8', $rawstr);
    return $newstr;
}

$ msg = '67714eac99c500200054006f006b0079006f002000530074006100740069006f006e003a0020';

echo unicode_to_textstring ($ str);

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.