什么是Perl的“标准字符串比较顺序”?
这是一个真正的双模双待,有回答我的两个最终目标:什么是Perl的“标准字符串比较顺序”?
- 什么是标准的字符串比较顺序,在力学方面?
- 这有什么更好的名称,所以我可以更新文档?
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相关行(线6698为提交7844ec1):
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核心并不知道任何事情;对于规范化,Perl核心并不知道任何事情;要在不同的表单之间进行精确的排序和比较,您需要通过Unicode::Normalize运行所有字符串,并将它们全部转换为相同的标准化表单。我无法评论哪一个最适合任何特定目的,主要是因为我没有线索。
此外,排序和cmp
受locale
编译指示的影响,如果它正在使用;它使用POSIX整理顺序。使用use locale
,一个8位语言环境和unicode一起是灾难的秘诀,但使用use locale
,UTF-8语言环境和unicode 应该有用。我不能说我已经尝试过了。无论如何,perllocale和perlunicode中有很多信息。
好的,我认为这是我需要的那种确认。我认为这是它的工作原理,但我不确定。有时会开会,所以我可以给你买啤酒。 :) – 2009-11-05 01:12:14
我一直有意参加一些会议,但我的日程安排通常让我工作到晚上7点或以后,所以我通常不得不错过他们。我会尽力解决一些问题。 – hobbs 2009-11-05 01:16:55
这是一个我不知道的非常有趣的事实。看起来像是一个聪明的设计决定给我! (事后明了,但嘿,最明智的决定是。) – 2009-11-05 13:02:19
我不能回答全部问题,所以让我磨练一个部分:
const I32 retval = memcmp((const void*)pv1, (const void*)pv2, cur1 < cur2 ? cur1 : cur2);
...看起来一旦
pv1
和pv2
,其被裹挟到char *
,现在只是逐字节地进行比较,因为它们被强制为void *
。这是怎么回事memcmp
很多。 memcmp
和strcmp
之间的主要区别区别是:一旦它看到一个NULL
(即'\0'
)
-
strcmp
将停止,和Perl允许标量已经嵌入NULL
小号 -
memcmp
往往运行得有点快比strcmp
但除此之外,你会得到相同的结果。
有一个简单的方法来看看他们是否按字节排序UTF-8序列:如果你这样做,你会得到A 2009-11-04 23:40:20
(回复自己)是的,当所有语言环境都设置为“C”时,我就是这么看的。似乎证实了你对源代码的分析。 – 2009-11-04 23:46:37
那么,你想观察的序列取决于你认为序列已经应该是什么,这就是为什么有一个Unicode排序算法。 :) – 2009-11-04 23:56:51