2009-11-04 44 views
19

这是一个真正的双模双待,有回答我的两个最终目标:什么是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); 

对我来说,看起来像一旦pv1pv2,其被裹挟到char *,现在只是比较逐字节,因为他们被强制为void *。那么memcmp会发生什么?看起来它只是根据我读过的各种文档比较位数?再次,我想知道我在从bytes-> utf8-> char-> bytes的行程中丢失了什么,就像Unicode标准化步骤一样。检出Perl_bytes_to_utf8utf8.c没有帮我回答这个问题。

作为一个便笺,我想知道这是否与Unicode Collation Algorithm一样?如果是这样,为什么Unicode::Collate存在?从它的外观来看,我不认为Perl的sort处理规范等价。

+0

有一个简单的方法来看看他们是否按字节排序UTF-8序列:如果你这样做,你会得到A 2009-11-04 23:40:20

+0

(回复自己)是的,当所有语言环境都设置为“C”时,我就是这么看的。似乎证实了你对源代码的分析。 – 2009-11-04 23:46:37

+0

那么,你想观察的序列取决于你认为序列已经应该是什么,这就是为什么有一个Unicode排序算法。 :) – 2009-11-04 23:56:51

回答

14

UTF-8具有根据字节值对UTF-8字符串进行逐字节排序的属性,它给出了与根据码点编号对码点进行排序相同的顺序。也就是说,我知道U + 2345的UTF-8表示在U + 1234的UTF-8表示之后按字典顺序排列。对于规范化,Perl核心并不知道任何事情;对于规范化,Perl核心并不知道任何事情;要在不同的表单之间进行精确的排序和比较,您需要通过Unicode::Normalize运行所有字符串,并将它们全部转换为相同的标准化表单。我无法评论哪一个最适合任何特定目的,主要是因为我没有线索。

此外,排序和cmplocale编译指示的影响,如果它正在使用;它使用POSIX整理顺序。使用use locale,一个8位语言环境和unicode一起是灾难的秘诀,但使用use locale,UTF-8语言环境和unicode 应该有用。我不能说我已经尝试过了。无论如何,perllocaleperlunicode中有很多信息。

+0

好的,我认为这是我需要的那种确认。我认为这是它的工作原理,但我不确定。有时会开会,所以我可以给你买啤酒。 :) – 2009-11-05 01:12:14

+0

我一直有意参加一些会议,但我的日程安排通常让我工作到晚上7点或以后,所以我通常不得不错过他们。我会尽力解决一些问题。 – hobbs 2009-11-05 01:16:55

+1

这是一个我不知道的非常有趣的事实。看起来像是一个聪明的设计决定给我! (事后明了,但嘿,最明智的决定是。) – 2009-11-05 13:02:19

5

我不能回答全部问题,所以让我磨练一个部分:

const I32 retval = memcmp((const void*)pv1, (const void*)pv2, cur1 < cur2 ? cur1 : cur2); 

...看起来一旦pv1pv2,其被裹挟到char *,现在只是逐字节地进行比较,因为它们被强制为void *。这是怎么回事memcmp

很多。 memcmpstrcmp之间的主要区别区别是:一旦它看到一个NULL(即'\0'

  1. strcmp将停止,和Perl允许标量已经嵌入NULL小号
  2. memcmp往往运行得有点快比strcmp

但除此之外,你会得到相同的结果。