bri*_*foy 19 sorting unicode perl collation
这真是一个双重问题,我的两个目标是:
Perl的sort文档说没有块,sort使用"标准字符串比较顺序".但那顺序是什么?应该有一个更好的名称.对于这个问题,我特别指的是语言环境不起作用的情况,因为它定义了自己的顺序.
在过去的几年中,我们通常将标准排序顺序称为"ASCIIbetically".这是在学习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
*/
Run Code Online (Sandbox Code Playgroud)
当Perl使用UTF-8进行排序时,它真正排序的是什么?字符串编码的字节,它代表的字符(包括标记可能?),还是其他什么?我认为这是sv.c中的相关行(提交7844ec1的第6698行):
pv1 = tpv = (char*)bytes_to_utf8((const U8*)pv1, &cur1);
Run Code Online (Sandbox Code Playgroud)
如果我正确地阅读(使用我生锈的C),pv1被强制转换为八位字节,变成UTF-8,然后强制转换为字符(在C意义上).我认为这意味着它按UTF-8编码排序(即UTF-8用来表示代码点的实际字节).另一种说法是,它不会对字素进行排序.我想我几乎已经说服自己,我正在读这个,但是你们中的一些人比我更了解这一点.
从那以后,下一个有趣的线是6708:
const I32 retval = memcmp((const void*)pv1, (const void*)pv2, cur1 < cur2 ? cur1 : cur2);
Run Code Online (Sandbox Code Playgroud)
对我来说,看起来像一次有pv1和pv2,其被裹挟到char *,现在因为他们被强制为只是比较逐字节void *.这是怎么回事memcmp,看起来它只是基于我到目前为止读过的各种文档比较位?再一次,我想知道我在行程中从bytes-> utf8-> char-> bytes中缺少什么,就像Unicode规范化步骤一样.检查出Perl_bytes_to_utf8在utf8.c没帮我回答这个问题.
作为旁注,我想知道这是否与Unicode校对算法相同?如果是,为什么Unicode :: Collate存在?从它的外观来看,我不认为Perl sort处理规范等价.
hob*_*bbs 14
UTF-8具有根据字节值逐字节地对UTF-8字符串进行排序的属性,与根据代码点编号对代码点进行排序的顺序相同.也就是说,我知道U + 2345的UTF-8表示在U + 1234的UTF-8表示之后是按字典顺序排列的.
至于规范化,Perl核心对它一无所知; 要在不同的表单之间进行准确的排序和比较,您希望通过Unicode :: Normalize运行所有字符串,并将它们全部转换为相同的规范化形式.我不能评论哪个最适合任何特定目的,主要是因为我不知道.
此外,排序并cmp受到locale编译指示的影响,如果它正在使用; 它使用POSIX整理顺序.使用use locale,一个8位语言环境和unicode是一个灾难的处方,但使用use localeUTF-8语言环境和unicode 应该有用.我不能说我已经尝试过了.无论如何,在perllocale和perlunicode中有很多信息.
我不能回答整个问题,所以让我磨练一下:
const I32 retval = memcmp((const void*)pv1, (const void*)pv2, cur1 < cur2 ? cur1 : cur2);
Run Code Online (Sandbox Code Playgroud)
...貌似一旦有
pv1和pv2,其被裹挟到char *,现在因为他们被强制为只是比较逐字节void *.这是怎么回事memcmp
差不多.memcmp和之间的主要差异strcmp是:
strcmp一旦看到NULL(即'\0'),它就会停止,并且Perl允许标量嵌入NULLsmemcmp 经常跑得快一点 strcmp但除此之外,你将获得相同的结果.