![unicode 和 UTF-8/16/32 的关系](https://linux22.com/image/1426788/unicode%20%E5%92%8C%20UTF-8%2F16%2F32%20%E7%9A%84%E5%85%B3%E7%B3%BB.png)
我不明白 UTF-8 与其其他变体之间的关系,并且在终端上得到了异常结果。例如,右箭头是:
0xE2 0x86 0x92
使用 UTF-8
但它是
0x2192
采用 UTF-16 和 Unicode
我不明白 E28692 怎么等于 2192。
此外,UTF-8 版本似乎无法在我的 Linux 终端上使用,该终端使用 UTF-8 编码和支持 Unicode 的 DejaVu 字体。例如,如果我输入
echo -e "\u2192"
然后我得到一个箭头,很好,正确,它起作用了。但是,如果我输入
echo -e "\xe2\x86\x92"
或者
echo -e "\x00\x00\x21\x92"
然后我得到了错误的图形。为什么我的十六进制序列是错误的?
答案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。
shell 中的转义序列
现在,为什么当你输入 UTF-8 序列时,你的 shell 不显示右箭头,让我们看看bash 手册。搜索关于转义序列的部分\xHH
,你会发现它被描述为
八位字符,其值为十六进制值 HH (一个或两个十六进制数字)
因此,您要求 bash 显示三个单独的两个字符序列,可能会给出类似的结果带抑扬符的拉丁文小写字母 A,选定区域的开始,以及私人用途字符某种类型。
答案2
Unicode 是一种字符集。UTF 是编码。
Unicode 定义了一组具有相应代码点的字符,即明确标识 Unicode 字符集中的字符的值。
例如根据unicode-table.com U+0041
对应于大写字母 A,U+03A3
是希腊字母大写字母 sigma (Σ),U+2603
是雪人 (☃)。U+
数字是代码点。Unicode 告诉我们什么符号对应什么代码点,但没有告诉我们如何用字节对这些代码点进行编码。
这时 UTF(Unicode 转换格式)就派上用场了。UTF 是一种编码:它将 Unicode 代码点映射到明确的字节序列。
UTF-32 是“愚蠢”的编码。所有 Unicode 代码点最多为 4 个字节长,因此 UTF-32 只是将代码点解释为 4 字节数字(32 位,因此得名),并大端字节顺序.所以
U+2603
编码为0x00002603
。UTF-32 非常简单,但也非常冗余。最常用的字符属于 ASCII 范围,在 Unicode 中用代码点 0-127 表示,因此在 UTF-32 编码的文件中,几乎每 4 个字节中就有 3 个是零。几乎每个英文句子在使用 UTF-32 而不是 ASCII 编码时都会变长 4 倍(以字节为单位)。
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 的回答对你的 shell 的行为进行了解释。