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

164

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

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

string str = "\u1000";

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

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

Telaclavo
источник
4
@diEcho: это только для сопоставления символов Юникода, но ОП хочет создать для этих символов.
Стефан Гериг
это может помочь: randomchaos.com/documents/?source=php_and_unicode
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функция, но вы можете ожидать, что она будет медленной.

Pacerier
источник
Идеально подходит для случаев, когда копирование / вставка символа маркера (\ 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);

chings228
источник