这真是一个双重问题,我的两个目标是:
Perl的sort文档说,如果没有阻止,sort
使用“标准字符串比较顺序”。但那顺序是什么?应该有一个更好的名称。对于这个问题,我特别指的是locale没有生效的情况,因为它定义了自己的顺序。
在过去的几年中,我们通常将标准排序顺序称为“ASCIIbetically”。它出现在Learning Perl和许多其他书籍中。但是,该术语已过时。自5.6以来,Perl一直是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 *
,现在只是逐字节进行比较,因为它们被强制转换为{{1 }}。那是void *
会发生什么,看起来它只是基于我到目前为止读过的各种文档来比较位?再一次,我想知道我在行程中从字节 - > utf8-&gt; char-&gt;字节中遗漏了什么,就像Unicode规范化步骤一样。在 utf8.c 中查看memcmp
并没有帮助我回答这个问题。
作为旁注,我想知道这是否与Unicode Collation Algorithm相同?如果是,为什么Unicode::Collate存在?从它的外观来看,我不认为Perl的Perl_bytes_to_utf8
处理规范等价。
答案 0 :(得分:14)
UTF-8具有根据字节值逐字节地对UTF-8字符串进行排序的属性,与根据代码点编号对代码点进行排序的顺序相同。也就是说,我知道U + 2345的UTF-8表示在U + 1234的UTF-8表示后按字典顺序排列。
至于规范化,Perl核心对此一无所知;要在不同的表单中进行准确的排序和比较,您希望通过Unicode::Normalize运行所有字符串,并将它们全部转换为相同的规范化表单。我无法评论哪个最适合任何特定目的,主要是因为我没有线索。
此外,如果cmp
编译指示正在使用,则排序和locale
会受到影响;它使用POSIX整理顺序。使用use locale
,8位语言环境和unicode是一个灾难的处方,但是使用use locale
,UTF-8语言环境和unicode 应该有效地工作。我不能说我已经尝试过了。无论如何,perllocale和perlunicode都有大量信息。
答案 1 :(得分:5)
我无法回答整个问题,所以让我在一个方面进行磨练:
const I32 retval = memcmp((const void*)pv1, (const void*)pv2, cur1 < cur2 ? cur1 : cur2);
...看起来一旦它
会发生什么pv1
和pv2
被强制转换为char *
,现在只是逐字节比较,因为它们被强制转换为{{1 }}。是void *
差不多。 memcmp
和memcmp
之间的主要差异是:
strcmp
会在看到strcmp
(即NULL
)后停止,而Perl允许标量嵌入'\0'
NULL
的运行速度通常比memcmp
但除此之外,你会得到相同的结果。