如何将两个代码点转换为一个?如果它是处理组合字素的默认方式,如何避免它呢?
> my $a = "a" ~ 0x304.chr
ā
> $a.codes
1
> $a.ords
(257)
UPD:在阅读documentation后,我看到所有输入都已标准化:
默认情况下,Perl6对所有输入和输出应用标准化除外 对于存储为UTF8-C8的文件名。
那么,有没有一种方法可以避免规范化,即获取输入并在不改变编码的情况下对其进行处理?
答案 0 :(得分:4)
根据Unicode报告(参见here),某些字符有多种表示方式。根据该报告:
某些角色被称为单身人士。归一化后,它们永远不会留在文本中。例子包括埃和欧姆符号,它们分别映射到它们的正常字母对应物a-with-ring和omega。
...
许多字符称为规范复合或预组合字符。在D形式中,它们被分解;在C形式中,它们通常预先组合。
在您提供的示例中,$a
包含一个可以用两种方式表示的字符串。首先,它对应于U + 0101(带有MACRON的LATIN SMALL LETTER A),它是Unicode代码点。其次,它可以表示为两个代码点组合形成一个等效字符(U + 0061 [LATIN SMALL LETTER A],然后是U + 0304 [COMBINING MACRON])。
这两个表示是NFC和NFD的基础。这些被称为规范化形式,因为它们允许使用最简洁或最可解构的表示来定期表示字符。某些组合字符在Unicode表中可能有两个条目(例如Ohm和Big Omega),但规范化表单只映射到一个条目。
NFD将所有字符分解为用于制作这些字符的所有代码点的列表,确保不使用预组合字符。
Perl6会自动使用NFC表示,但您可以使用NFD
上的Str
转换方法获取NFD(或 D 分解)版本。
my $a = "a" ~ 0x304.chr;
say $a.codes; # OUTPUT: 1
# This is because the concatenation
# is using NFC by default.
say $a.ords; # OUTPUT: (257)
say $a.NFD.codes; # OUTPUT: 2
say $a.NFD.list; # OUTPUT: (97 772)
NFC和NFD都很有用,但它们用于不同的目的。据我所知,没有办法避免输入的规范化,但您可以使用NFC
和NFD
转换方法将输入转换为您需要的任何表示形式。