为什么有些Unicode字符无法打印到我的终端上?


16

我正在使用Adobe Source Code Pro字体通过简单的终端运行Arch Linux。我的语言环境已正确设置为LANG=en_US.UTF-8

我想将代表扑克牌的Unicode字符打印到我的终端上。我正在使用Wikipedia作参考

卡套装的Unicode字符可以正常工作。例如,发行

$ printf "\u2660"

在屏幕上打印黑色的心。

但是,我在使用特定的纸牌时遇到了麻烦。发行

$ printf "\u1F0A1"

打印符号Ἂ1而不是黑桃🂡。怎么了

这个问题在多个终端(urxvt,xterm,白蚁)和我尝试过的每种字体(DejaVu,Inconsolata)上仍然存在。


警告:如果由printf处理,则为非标准增强功能。因此,不要指望这样的转义行之有效。参见:pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
凌晨

Answers:


27

help printf遵循printf(1)解释的转义序列,GNU printf的文档说:

printf解释ISO C 99中引入的两种字符语法: \u对于16位Unicode(ISO / IEC 10646)字符,指定为四个十六进制数字hhhh\U对于32位Unicode字符,指定为八个十六进制数字hhhhhhhhprintf根据LC_CTYPE语言环境输出Unicode字符。此语法无法指定范围为U + 0000…U + 009F,U + D800…U + DFFF的Unicode字符,但U + 0024($),U + 0040(@)和U + 0060(`)除外。 。

在Bash手册中为ANSI C报价和指定了类似的内容echo

\uHHHH
Unicode(ISO / IEC 10646)字符,其值为十六进制值HHHH(一到四个十六进制数字)

\UHHHHHHHH
Unicode(ISO / IEC 10646)字符,其值为十六进制值HHHHHHHH(1至8个十六进制数字)

简而言之:\u不是5个十六进制数字。是\U

# printf "\u2660 \u1F0A1 \U1F0A1\n"
 1 🂡

2

穆鲁的答案是完全正确的,只是为了澄清一点:

在打印时\u1F0A1,这被解释为16位Unicode转义\u1F0A,其后是文字字符1(因为\u使用以下四个字符,因此,不多也不少)。然后,U + 1F0A给出一个带有几个变音符号的希腊字母alpha(确切地说是希腊大写字母Alpha和Psili和Varia)。

如果您想在Unicode转义中使用16位以上的字符,则需要使用\U,它需要使用8个字符的十六进制值:这\U0001F0A1将为您提供扑克牌。


\U0001F0A1实际上比\U1F0A1。这是GNU独立printf实用程序,它首先引入了这些\uXXXX/ \UXXXXXXXX序列,并且确实需要4位数字\u和8 位数字\UprintfGNU Shell的内置,ksh93和zsh之类的其他实现则比较松懈。无论如何printf '\u/\U'不是POSIX。但是POSIX将指定zsh,$'\U1F0A1'并且不需要全部8位数字。
斯特凡Chazelas

@StéphaneChazelas有趣的是,我一直认为POSIX会采用八位数字。如果您想避免在代码后捕获多余的字母和数字,我认为八位数版本在zsh中仍然有效。
德拉科尼斯

是的,\uxxxx高达 4个位数,并\Uxxxxxxxx多达 8个位数。请注意,Unicode现在仅限于代码点0到0x10FFFF(UTF16带来的限制),因此代码点永远不会超过6个数字(仍将\U123456789被解释为代码点0x12345678的字符,后跟9并失败)。的POSIX规范$'\u\U'仍未最终确定(请参阅austingroupbugs.net/view.php?id=249)。在较早的草案中,他们需要所有4/8位数字,但后来有所更改(应我的要求)。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.