unicode 和 UTF-8/16/32 的关系

unicode 和 UTF-8/16/32 的关系

我不明白 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 的行为进行了解释。

相关内容