2009-11-04 79 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

但除此之外,你會得到相同的結果。