Символ Unicode в рядку PHP


164

Це питання виглядає бентежно просто, але я не змогла знайти відповідь.

Який PHP еквівалентний наступному рядку коду C #?

string str = "\u1000";

Цей зразок створює рядок з єдиним символом Unicode, числове числове значення Unicode - 1000 у шістнадцятковій цифрі (4096 у десятковій частині).

Тобто в PHP, як я можу створити рядок з одним символом Unicode, чиє числове значення "Unicode" відоме?



4
@diEcho: це лише для відповідності символів Unicode, але ОП хоче створити для цих символів.
— Стефан Гегріг

це може допомогти: 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 (великий ендіан) та кодовою точкою Unicode:

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

9
JSON - це не JavaScript.
— Gumbo

4
@Gumbo: Я знаю, що це не має ніякого значення. 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" .

Тепер можна легко записати символи Unicode, використовуючи подвійне цитування або рядок heredoc , не викликаючи жодної функції.

$unicodeChar = "\u{1000}";

Це можна використовувати так: wordwrap($longLongText, 20, "\u{200B}", true);( нульової ширини це місце )
— sanmai

5
Я вважаю, що ОП хотіла цієї відповіді, а не прийнятої відповіді. У будь-якому разі, коли я шукав "Unicode в PHP", це було тому, що я хотів цю відповідь, а не прийняту відповідь. Можливо, "\ u {abcd}" не існувало, коли це питання було вперше задано. Якщо так, прийняту відповідь зараз слід перемістити.
— Адам Чалкрафт

23

Цікаво, чому ніхто ще не згадав про це, але ви можете зробити майже еквівалентну версію, використовуючи послідовності втечі в подвійних цитованих рядках :

\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 не знає цих послідовностей виходу 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");

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)

Зауважте, що, як згадує Пак’єр в іншій відповіді, цей двійковий код унікальний для конкретного кодування символів. У наведеному вище прикладі \xE2\x80\x8Aє двійкове кодування для U + 200A в UTF-8.

Наступне питання, як ви отримаєте від U+200Aдо \xE2\x80\x8A?

Нижче наведено скрипт PHP для створення послідовності запуску для будь-якого символу, заснованого на рядку 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.