十六进制代码(\ x)和unicode(\ u)字符之间有什么区别?

Ric*_*ton 24 unicode hex r

来自?Quotes:

\xnn   character with given hex code (1 or 2 hex digits)  
\unnnn Unicode character with given code (1--4 hex digits)
Run Code Online (Sandbox Code Playgroud)

在Unicode字符只有一个或两个数字的情况下,我希望这些字符是相同的.实际上,?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!"
Run Code Online (Sandbox Code Playgroud)

但是,在Linux下,当我试图打印一个英镑符号时,我明白了

cat("\ua3")
## £
cat("\xa3")
## ?
Run Code Online (Sandbox Code Playgroud)

也就是说,\x十六进制代码无法正确显示.(这种行为持续存在于我尝试的任何区域设置.)在Windows 7下,两个版本都显示一个井号.

如果我转换为整数然后返回,则在Linux下正确显示井号.

cat(intToUtf8(utf8ToInt("\xa3")))
## £
Run Code Online (Sandbox Code Playgroud)

顺便说一下,这在Windows下不起作用,因为utf8ToInt("\xa3")返回NA.

某些\x字符NA在Windows下返回但在Linux下引发错误.例如:

utf8ToInt("\xf0")
## Error in utf8ToInt("\xf0") : invalid UTF-8 string
Run Code Online (Sandbox Code Playgroud)

("\uf0"是一个有效的角色.)

这些例子表明字符\x\u形式之间存在一些差异,这些差异似乎是特定于操作系统的,但我看不出它们如何被定义的任何逻辑.

这两种字符形式有什么区别?

一二三*_*一二三 23

转义序列\xNN将原始字节NN插入字符串,而\uNN将Unicode代码点的UTF-8字节NN插入UTF-8字符串:

> charToRaw('\xA3')
[1] a3
> charToRaw('\uA3')
[1] c2 a3
Run Code Online (Sandbox Code Playgroud)

这两种类型的转义序列不能混合在同一个字符串中:

> '\ua3\xa3'
Error: mixing Unicode and octal/hex escapes in a string is not allowed
Run Code Online (Sandbox Code Playgroud)

这是因为转义序列还定义了字符串的编码.一个\uNN序列明确地设置整个字符串"UTF-8",而的编码\xNN离开它在默认的"未知"(又名天然)编码:

> Encoding('\xa3')
[1] "unknown"
> Encoding('\ua3')
[1] "UTF-8"
Run Code Online (Sandbox Code Playgroud)

这在打印字符串时变得很重要,因为它们需要转换为适当的输出编码(例如,控制台的编码).具有已定义编码的字符串可以适当地转换(请参阅参考资料enc2native),但具有"未知"编码的字符串只是按原样输出:

  • 在Linux上,您的控制台可能需要UTF-8文本,并且由于0xA3它不是有效的UTF-8序列,它会为您提供" ".
  • 在Windows上,您的控制台可能正在使用Windows-1252文本,正如0xA3"£"的正确编码一样,这就是您所看到的.(当字符串\uA3为时,将发生从UTF-8到Windows-1252的转换.)

如果明确设置了编码,则在Linux上进行适当的转换:

> s <- '\xa3'
> Encoding(s) <- 'latin1'
> cat(s)
£
Run Code Online (Sandbox Code Playgroud)