这确实是一个双重问题,我的两个最终目标有以下答案:
Perl 的 sort 文档说没有 block ,
sort
使用“标准字符串比较顺序”。但是这个命令是什么?它应该有一个更好的名字。对于这个问题,我特指 locale 的情况。无效,因为它定义了它自己的顺序。在过去的几年里,我们通常将标准排序顺序称为“ASCIIbetically”。它在 Learning Perl和许多其他书籍。但是,该术语已过时。 Perl 从 5.6 开始就支持 Unicode。谈论 ASCII 是老派。因为 Perl 也支持 Unicode,所以它知道字符串。在 sv.c 中,
Perl_sv_cmp
了解locale
, bytes
, 和 UTF-8。前两个很容易。但我对第三个没有信心。/*
=for apidoc sv_cmp
Compares the strings in two SVs. Returns -1, 0, or 1 indicating whether the
string in C<sv1> is less than, equal to, or greater than the string in
C<sv2>. Is UTF-8 and 'use bytes' aware, handles get magic, and will
coerce its args to strings if necessary. See also C<sv_cmp_locale>.
=cut
*/
当 Perl 使用 UTF-8 进行排序时,它真正的排序是什么?字符串编码的字节,它代表的字符(可能包括标记?),还是其他?我认为这是 sv.c 中的相关行(提交 7844ec1 的第 6698 行):
pv1 = tpv = (char*)bytes_to_utf8((const U8*)pv1, &cur1);
如果我没看错(使用我生锈的 C),
pv1
被强制转换为八位字节,转换为 UTF-8,然后被转换为字符(在 C 意义上)。我认为这意味着它是按 UTF-8 编码排序的(即 UTF-8 用来表示代码点的实际字节)。另一种说法是它不对字素进行排序。我想我几乎已经说服自己我没看错,但你们中的一些人比我更了解这一点。由此,下一个有趣的行是 6708:
const I32 retval = memcmp((const void*)pv1, (const void*)pv2, cur1 < cur2 ? cur1 : cur2);
对我来说,它看起来就像拥有
pv1
和 pv2
, 被强制为 char *
, 现在只是逐字节比较,因为它们被强制为 void *
. memcmp
会发生这种情况吗? ,看起来它只是根据我迄今为止阅读的各种文档比较位?同样,我想知道我在从 bytes->utf8->char->bytes 的旅程中缺少什么,比如可能是 Unicode 规范化步骤。退房Perl_bytes_to_utf8
在 utf8.c 中并没有帮助我回答这个问题。作为旁注,我想知道这是否与 Unicode Collation Algorithm 相同。 ?如果是,为什么 Unicode::Collate存在?从外观上看,我不认为 Perl 的
sort
处理规范等价。
最佳答案
UTF-8 具有这样的特性,即根据字节值对 UTF-8 字符串进行逐字节排序与根据代码点编号逐个代码点对其进行排序的排序相同。也就是说,我不看就知道 U+2345 的 UTF-8 表示在 U+1234 的 UTF-8 表示之后的字典顺序。
至于规范化,Perl 核心对此一无所知。为了获得准确的排序和不同形式之间的比较,您希望通过 Unicode::Normalize 运行所有字符串并将它们全部转换为相同的规范化形式。我无法评论哪个最适合任何特定目的,主要是因为我不知道。
此外,排序和cmp
受 locale
的影响pragma 如果它正在使用中;它使用 POSIX 排序规则。使用 use locale
, 8 位语言环境和 unicode 一起是灾难的根源,但使用 use locale
, UTF-8 语言环境和 unicode 应该有用。我不能说我试过了。 perllocale 中有大量信息和 perlunicode反正。
关于perl - Perl 的 "standard string comparison order"是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1677258/