1

Я не понимаю взаимосвязи между UTF-8 и его другими вариантами и получаю аномальные результаты на терминале. Например, стрелка вправо:

0xE2 0x86 0x92 в UTF-8

но это

0x2192 в UTF-16 в UTF-16 и Unicode

Я не понимаю, как E28692 эквивалентен 2192.

Кроме того, версия UTF-8, похоже, не работает в моем терминале Linux, который использует кодировку UTF-8 со шрифтом DejaVu, который поддерживает Unicode. Например, если я введу

echo -e "\u2192"

Тогда я получаю стрелу, отлично, правильно, это работает. Но если я войду

echo -e "\xe2\x86\x92" или

echo -e "\x00\x00\x21\x92"

Тогда я получаю неправильную графику. Почему мои шестнадцатеричные последовательности неверны?

2 ответа2

2

Юникод это набор символов. UTF - это кодировки.

Unicode определяет набор символов с соответствующими кодовыми точками, т.е. значения, которые однозначно идентифицируют символы в наборе символов Unicode.

Например, согласно unicode-table.com U+0041 соответствует столице A, U+03A3 - греческая заглавная сигма (Σ), а U+2603 - снеговик (☃). U+ цифры - это кодовые точки. Юникод сообщает нам, какой символ соответствует какой кодовой точке, но не говорит нам, как кодировать эти кодовые точки в байтах.

Это где UTF (Unicode Transformation Format) вступает в игру. UTF - это кодировка: она отображает кодовые точки Unicode в однозначные последовательности байтов.

  • UTF-32 - это "тупая" кодировка. Все кодовые точки Unicode имеют длину не более 4 байтов, поэтому UTF-32 просто интерпретирует кодовую точку как 4-байтовое число (32-битное, отсюда и название) с порядком байтов с прямым порядком байтов. Таким образом, U+2603 кодируется как 0x00002603 .

    UTF-32 очень прост, но также очень избыточен. Наиболее часто используемые символы попадают в диапазон ASCII и представлены кодовыми точками 0-127 в Unicode, поэтому в файлах с кодировкой UTF-32 почти 3 из 4 байтов будут нулями. Почти каждое английское предложение становится в 4 раза длиннее (в байтах) при кодировании в UTF-32 вместо ASCII.

  • UTF-8 (очень распространенный в Интернете) использует только 1 байт для символов ASCII, поэтому он не вносит никаких издержек в файлы только для ASCII (каждый файл ASCII также является файлом UTF-8 с тем же содержимым). Другие символы требуют до 6 байтов.

  • UTF-16 (используется Windows, просто чтобы назвать один пример) является компромиссом между UTF-32 и UTF-8. Кодовые точки кодируются в 16-битные или 32-битные последовательности. В большинстве случаев он более избыточен, чем UTF-8, но проще в обслуживании и быстрее обрабатывается.

Разные символы могут иметь разные представления в разных кодировках UTF-x. Например, последовательности UTF-8 могут занимать до 6 байтов, в то время как последовательности UTF-16 имеют длину не более 4 байтов, хотя обе кодируют один и тот же набор символов (Unicode). Более мелкозернистые кодировки (UTF-8) используют больше битов, чтобы указать длину последовательности, поэтому для кодовых значений с высокими значениями кодирования более длинные и менее оптимальные значения.

Ответ dsolimano объясняет поведение вашей оболочки.

1

Кодовые точки Unicode, закодированные в UTF-8

Они эквивалентны из-за https://en.wikipedia.org/wiki/UTF-8#Description, см. Алгоритм для преобразования кодовых точек Unicode в UTF-8. Это идет так.

Ваша кодовая точка 0x2192 находится между U+0800 и U+FFFF. Итак, мы используем третий ряд таблицы.

                         Byte 1     Byte 2      Byte 3
16  U+0800  U+FFFF  3   1110xxxx    10xxxxxx    10xxxxxx

0x2192 в двоичном виде - 0010 0001 1001 0010 . Давайте подключим это, а затем преобразовать их обратно в гекс

16  U+0800  U+FFFF  3   11100010    10000110    10010010
                    3   E   2       8   6       9   2

E28692 другими словами.

Escape-последовательности в вашей оболочке

Теперь о том, почему ваша оболочка не отображает стрелку вправо при вводе последовательности UTF-8, давайте посмотрим на руководство по bash. Найдите раздел по escape-последовательности \xHH и вы увидите, что он описан как

восьмибитный символ, значение которого является шестнадцатеричным значением HH (одна или две шестнадцатеричные цифры)

Итак, вы просите bash отобразить три отдельные последовательности из двух символов, вероятно, давая вам что-то вроде LATIN SMALL LETTER A WITH CIRCUMFLEX, START OF SELECTED AREA и какой-то символ частного использования .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .