Unicode字符默认排序规则表

问题描述 投票:1回答:3

我不知道这个问题究竟属于哪个网站,所以在此发布。

我在RHEL 6.4上使用Postgresql 9.2并观察以下内容:

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

postgresql unicode collation rhel
3个回答
2
投票

这不是错位的。它可能对你而言,但它不适合我。 :-)严肃地说,Unicode没有正确的行为;根本就不可能。字符集是映射;排序规则是一组特定于语言环境的规则,用于对该组中的字符进行排序 - 即使在同一语言环境中,也可以有多个排序规则。

ICU博士提供了丰富的例子,说明这种东西是多么棘手,万一你好奇。引用广泛:

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

[以下是语言在排序字符串中的一些变化方式:

字母A-Z可以按与英语不同的顺序排序。例如,在立陶宛语中,“y”在“i”和“k”之间排序。

字母组合可以被视为一个字母。例如,在传统的西班牙语中,“ch”被视为单个字母,并在“c”和“d”之间排序。

重音字母可视为非重音字母的次要变体。例如,“é”可以被视为等同于“e”。

重音字母可以视为不同的字母。例如,丹麦语中的“Å”被视为在“Z”之后排序的单独字母。

在一种语言中被认为是不同的非重音字母在另一种语言中可能是不明显的。例如,根据英语,字母“v”和“w”是两个不同的字母。但是,“v”和“w”被认为是瑞典语中相同字母的变体形式。

一封信可以被视为两个字母。例如,在传统的德语中,“ä”被比作好像是“ae”。

泰国要求撤销某些字母的顺序。

法语要求在字符串末尾用重音符号排序的字母在字符串开头的重音符号之前进行排序。例如,“côte”这个词在“coté”之前排序,因为最后“e”的尖锐重音比“o”上的旋律更重要。

有时小写字母排在大写字母之前。在其他情况下需要相反。例如,小写字母通常在英文大写字母之前排序。拉脱维亚字母恰恰相反。

即使是相同的语言,不同的应用程序也可能需要不同的排序顺序例如,在德语词典中,“öf”将出现在“of”之前。在电话簿中情况恰恰相反。

由于政府法规或Unicode中的新字符/脚本,排序顺序可能会随时间而变化。


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(如“Root collat​​ion”中的UTS#35中所述)。它列出了西里尔文A之后的西里尔语schwa,即你期望的顺序。

还有en_US_POSIX语言环境的数据,并且该语言环境包含一些修改,但没有更改任何非ASCII的语言环境。

看来你的系统中安装的en_US语言环境使用了一个剪裁,它将schwa放在E旁边,可能是因为它们的形式相似。有人认为,对美国英语观众的惊喜会比A之后排序schwa更少:问问人们是什么,看看有多少人会告诉你这是一个“颠倒的E”。这不是对或错,但如果你问我,它似乎比CLDR中的校对更合适。


1
投票

Postgresql使用操作系统提供的语言环境。在您的设置中,语言环境由glibc提供。 Glibc使用ISO 14651的“古老”版本的大量修改版本(有关尝试更新glibc语言环境数据时当前痛苦的信息,请参阅glibc Bug 14095 - Review / update collation data from Unicode / ISO 14651)。

从glibc 2.28开始,将于2018-08-01发布,glibc将使用来自ISO 14651:2016的数据(与Unicode 9同步),并将给出OP期望en_US的订单。

ISO 14651是用于比较字符串和公共模板可定制排序的描述的方法,它类似于UCA,但有一些差异。 CTT(通用模板表)是DUCET的ISO14651等效物,它们是对齐的。

CYRILLIC SMALL LETTER SCHWA第一次出现在glibc的校对表中是为了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_t1,该排序最终被移动到文件Bug 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的基础是哈萨克和塔塔尔的排序,这是差异的来源。

© www.soinside.com 2019 - 2024. All rights reserved.