2013-05-29 64 views
1

我不知道這個問題屬於哪個網站,所以在此張貼。Unicode字符默認排序表

我使用PostgreSQL 9.2 RHEL 6.4和遵守下列規定:

select foo 
from unnest('{а,ә,б,в,г,д,е,ж}'::text[]) as foo 
order by foo collate "kk_KZ.utf8" 

а 
ә 
б 
в 
г 
д 
е 
ж 

select foo 
from unnest('{а,ә,б,в,г,д,е,ж}'::text[]) as foo 
order by foo collate "en_US.utf8" 

а 
б 
в 
г 
д 
е 
ә -- misplaced 
ж 

此外,我發現有默認的Unicode排序規則元素表[1],其中列出了有問題的字符(04D9; [.199D.0020.0002.04D9]#CYRILLIC SMALL LETTER SCHWA)。

據我所知,希望西里爾文字符能夠通過「en_US.utf8」語言環境正確處理是愚蠢的,但是Unicode或任何其他相關標準正確行爲的情況下,字符通常不屬於用於整理的語言/區域設置?

[1] http://www.unicode.org/Public/UCA/latest/allkeys.txt

+0

僅供參考:glibc 2.28將於2018-08-01發佈,已與ISO-14651:2016同步(本身與Unicode 9同步),並將使用您預期的en_US訂單。 – ninjalj

回答

2

它沒有錯。這可能是你的,但它不是我。 :-)嚴肅地說,Unicode沒有正確的行爲;根本不可能。字符集是一個映射;排序規則是一組特定於語言環境的規則,用於對該集中的字符進行排序 - 即使在相同的語言環境中,也可以有多個排序規則。

ICU文件有豐富多彩的例子,說明這種東西是多麼棘手,萬一你好奇。廣泛引用:

http://userguide.icu-project.org/collation

[H] ERE是一些語言在訂貨串改變方式:

字母A-Z可以以不同的順序進行排序比英語。例如,在立陶宛語中,「y」在「i」和「k」之間排序。

字母組合可以被視爲他們是一個字母。例如,在傳統的西班牙語中,「ch」被視爲單個字母,並在「c」和「d」之間進行排序。

重音字母可以視爲無重音字母的次要變體。例如,「é」可以等同於「e」。

重音字母可以視爲不同的字母。例如,丹麥語中的「Å」被視爲在「Z」後面排列的單獨字母。

在一種語言中被認爲截然不同的不重疊的字母可能在另一種語言中不明顯。例如,根據英語,字母「v」和「w」是兩個不同的字母。但是,「v」和「w」被認爲是瑞典語中同一個字母的不同形式。

一封信可以看作是兩個字母。例如,在傳統的德語中,「ä」被比作「ae」。

泰語要求顛倒某些字母的順序。

法語要求在字符串末尾以重音符號排序的字母應排在字符串開頭的重音符之前。例如,「côte」一詞在「coté」之前排序,因爲最後的「e」上的尖銳重音比「o」上的旋律重要。

有時小寫字母在大寫字母之前排序。相反在其他情況下是必需的。例如,小寫字母通常以英文大寫字母排序。拉脫維亞的信件完全相反。

即使使用相同的語言,不同的應用程序可能需要不同的排序順序。例如,在德語字典中,「öf」會在「之前」出現。在電話簿中,情況恰恰相反。

由於政府法規或Unicode中的新字符/腳本,排序順序可能隨時間而改變。

+0

當字符在某些語言環境中沒有意義時,沒有任何「回退到默認排序規則」嗎? – Tair

2

Unicode Collation Algorithm允許對DUCET進行任何裁剪。

沒有「正確的」行爲。有不同的行爲可以預期,最合適的取決於背景和觀衆。有時任何的行爲可能是正確的,因爲沒有任何理由在美國英語整理中強制使用西里爾語的更高順序。

Common Locale Data Repository爲DUCET提供了區域特定的裁縫。 CLDR使用LDML(區域設置數據標記語言)來指定定製,並且語法由Unicode Technical Specification #35, part 5給出。

由CLDR爲en_US提供的數據的最新版本沒有定製:它使用modified version of the DUCET(如UTS#35在「根整理」下所述)。它列出了西里爾文A之後的西里爾文schwa,即您期望的順序。

en_US_POSIX區域設置也有數據,其中包含一些修改,但沒有更改任何不是ASCII的內容。

看起來你的系統中安裝的en_US語言環境使用了裁剪方式,將schwa放在E旁邊,可能是因爲它們有相似的形式。有人可能會認爲,對A後的美國英語聽衆來說,比排序schwa更少會帶來驚喜。問問人們這是什麼,看看有多少人會告訴你這是一個「顛倒的E」。這不對還是錯,但如果你問我,似乎比CLDR中找到的排序規則更合適。

+0

你有沒有提到哪些「任何行爲都可能是正確的」?謝謝! – Tair

+0

不是。我是基於這樣一個事實,即英語沒有排列西裏爾字母的規則(應該是顯而易見的原因),並且事實上一些觀衆會期望一個訂單,而另一些人會期望另一個訂單。 –

1

Postgresql使用操作系統提供的語言環境。在你的設置中,語言環境由glibc提供。 Glibc使用ISO 14651「古老」版本的重大修改版本(關於試圖更新glibc語言環境數據的當前痛苦信息,請參閱glibc Bug 14095 - Review/update collation data from Unicode/ISO 14651)。

作爲glibc的2.28,待上2018年8月1日公佈的,glibc的將使用數據從ISO 14651:2016(其被同步到Unicode 9),並且將得到OP預計,EN_US的順序。

ISO 14651是比較字符串的方法和通用模板可裁剪排序的描述,它與UCA類似,有一些不同之處。 CTT(通用模板表)是DUCET的ISO14651等效值,並且它們是對齊的。

第一次在glibc的排序表中出現CYRILLIC SMALL LETTER SCHWA是針對az_AZ區域設置(阿塞拜疆),它在CYRILLIC SMALL LETTER IE之後排序。這相當於:

commit fcababc4e18fee81940dab20f7c40b1e1fb67209 
Author: Ulrich Drepper <[email protected]> 
Date: Fri Aug 3 08:42:28 2001 +0000 

    Update. 

    2001-08-03 Ulrich Drepper <[email protected]> 

     * locale/iso-639.def: Add Tigrinya. 

從那裏,排序最終移至文件iso14651_t1Bug 672 - Include iso14651_t1 in collation rules,這是簡化的glibc語言環境數據的努力。這相當於:

commit 5d2489928c0040d2a71dd0e63c801f2cf98e7efc 
Author: Ulrich Drepper <[email protected]> 
Date: Sun Feb 18 04:34:28 2007 +0000 

    [BZ #672] 

    2005-01-16 Denis Barbier <[email protected]> 
     [BZ #672] 
     * locales/ca_ES: Replace current collation rules by including 
     iso14651_t1 and adding extra rules if needed. There should be 
     no noticeable changes in sorted text. only ligatures and 
     ignoreable characters have modified weights. 
     * locales/da_DK: Likewise. 
     * locales/en_CA: Likewise. 
     * locales/es_US: Likewise. 
     * locales/fi_FI: Likewise. 
     * locales/nb_NO: Likewise. 

     [BZ #672] 
     * locales/iso14651_t1: Simplified. Extended. 

在glibc的啓動大多數地區從iso14651_t1,並調整它,這是你與en_US看到的。

雖然glibc根據其在阿塞拜疆的默認排序,但DUCET將其基於哈薩克語和韃靼語的排序,這是差異來自的地方。