Какая разница между шестнадцатеричным кодом (\ x) и символом unicode (\ u)?
От ?Quotes
:
\ xnn с заданным шестнадцатеричным кодом (1 или 2 шестнадцатеричных разряда)
\ unnn Unicode-символ с заданным кодом (1--4 шестнадцатеричных цифр)
В случае, когда символ Юникода имеет только одну или две цифры, я ожидал бы, что эти символы будут одинаковыми. На самом деле, один из примеров на странице справки ?Quotes
показывает:
"\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21"
## [1] "Hello World!"
"\u48\u65\u6c\u6c\u6f\u20\u57\u6f\u72\u6c\u64\u21"
## [1] "Hello World!"
Однако, под Linux, при попытке распечатать знак фунта, я вижу
cat("\ua3")
## £
cat("\xa3")
## �
То есть шестнадцатеричный код \x
не отображается правильно. (Это поведение сохранялось в любой локали, которую я пробовал.) В Windows 7 обе версии показывают знак фунта.
Если я конвертирую в целое и обратно, тогда знак фунта отображается правильно в Linux.
cat(intToUtf8(utf8ToInt("\xa3")))
## £
Кстати, это не работает под Windows, так как utf8ToInt("\xa3")
возвращает NA
.
Некоторые \x
символы возвращают NA
под Windows, но вызывают ошибку в Linux. Например:
utf8ToInt("\xf0")
## Error in utf8ToInt("\xf0") : invalid UTF-8 string
("\uf0"
является допустимым символом.)
Эти примеры показывают, что существуют некоторые различия между формами символов \x
и \u
, которые кажутся специфичными для ОС, но я не вижу никакой логики в том, как они определены.
В чем разница между этими двумя символьными формами?
Ответы
Ответ 1
Управляющая последовательность \xNN
вставляет исходный байт NN
в строку, тогда как \uNN
вставляет байты UTF-8 для кодовой точки Unicode NN
в строку UTF-8:
> charToRaw('\xA3')
[1] a3
> charToRaw('\uA3')
[1] c2 a3
Эти два типа escape-последовательности не могут быть смешаны в одной строке:
> '\ua3\xa3'
Error: mixing Unicode and octal/hex escapes in a string is not allowed
Это потому, что escape-последовательности также определяют кодировку строки. Последовательность \uNN
явно устанавливает кодировку всей строки в "UTF-8", тогда как \xNN
оставляет ее в по умолчанию "неизвестной" (ака. Родной) кодировке:
> Encoding('\xa3')
[1] "unknown"
> Encoding('\ua3')
[1] "UTF-8"
Это становится важным при печати строк, поскольку их необходимо преобразовать в соответствующую выходную кодировку (например, консоль). Строки с определенным кодированием могут быть преобразованы соответствующим образом (см. enc2native
), но те, у которых есть "неизвестная" кодировка, просто выводятся как есть:
- В Linux ваша консоль, вероятно, ожидает текст UTF-8, а поскольку
0xA3
не является допустимой последовательностью UTF-8, она дает вам "".
- В Windows ваша консоль, вероятно, ожидает текст Windows-1252, а как
0xA3
- правильная кодировка для "£", это то, что вы видите. (Когда строка \uA3
, происходит преобразование из UTF-8 в Windows-1252.)
Если кодировка задана явно, соответствующее преобразование будет выполняться в Linux:
> s <- '\xa3'
> Encoding(s) <- 'latin1'
> cat(s)
£
Ответ 2
Взято из Python 2.7 Unicode КАК ДОКУМЕНТЫ:
В исходном коде Python литералы Unicode записываются как строки с префиксом "u" или "U": u'abcdefghijk. Конкретный код точки могут быть записаны с помощью escape-последовательности\u, за которой следует четырьмя шестнадцатеричными цифрами, дающими кодовую точку. Управляющая последовательность \U является аналогично, но ожидает 8 шестнадцатеричных цифр, а не 4.
Литералы Unicode также могут использовать те же escape-последовательности, что и 8-битные строки, включая \x, но\x принимает только две шестнадцатеричные цифры, поэтому он не может выражают произвольную кодовую точку. Октальные экраны могут подниматься до U + 01ff, который является восьмеричным 777.
Проще говоря (надеюсь):
\ 0nn - указывает двузначную восьмеричную escape-последовательность юникода "кодовая точка".
\ xnn - указывает двузначную шестнадцатеричную "кодовую точку" юникода.
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\ Unnnnnnnnn - задает восьмеричную шестнадцатеричную "кодовую точку" юникода.
Необходимо использовать полное количество цифр, дополненных ведущими 0.
Например:
>>> ord(u'\010')
8
>>> ord(u'\x10')
16
>>> ord(u'\020')
16
>>> ord(u'\x20')
32
>>> ord(u'\u0020')
32
>>> ord(u'\U00000020')
32
>>> ord(u'\u1000')
4096