我不知道这个问题到底属于哪个网站,所以把它贴在这里吧。
我在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 #西里尔文小写字母SCHWA)。
我理解期望西里尔字符被"en_US.utf8“区域设置正确处理是愚蠢的,但是在字符通常不属于用于排序的语言/区域设置的情况下,Unicode或任何其他相关标准的正确行为是什么?
1
发布于 2015-12-04 09:31:05
Postgresql使用操作系统提供的区域设置。在您的设置中,locale由glibc提供。Glibc使用了一个经过大量修改的“老”版本的ISO 14651 (有关更新glibc语言环境数据的当前难题的信息,请参阅glibc Bug 14095 - Review / update collation data from Unicode / ISO 14651 )。
从2018年8月01日发布的glibc2.28开始,glibc将使用来自 14651:2016的数据(与unicode9同步),并将给出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 <drepper@redhat.com>
Date: Fri Aug 3 08:42:28 2001 +0000
Update.
2001-08-03 Ulrich Drepper <drepper@redhat.com>
* locale/iso-639.def: Add Tigrinya.从那时起,这种排序最终按照Bug 672 - Include iso14651_t1 in collation rules移到了文件iso14651_t1中,这是为了简化glibc语言环境数据。这对应于:
commit 5d2489928c0040d2a71dd0e63c801f2cf98e7efc
Author: Ulrich Drepper <drepper@redhat.com>
Date: Sun Feb 18 04:34:28 2007 +0000
[BZ #672]
2005-01-16 Denis Barbier <barbier@linuxfr.org>
[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基于哈萨克语和塔塔尔语的排序,这就是差异所在。
发布于 2013-05-29 23:37:25
不是放错地方了。可能是对你,但不是对我。:-)说真的,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中的新字符/脚本而改变。
发布于 2013-05-29 23:50:57
Unicode Collation Algorithm允许对DUCET进行任何裁剪。
没有“正确”的行为。人们可以期待各种各样的行为,而最合适的行为取决于上下文和受众。有时,任何行为都可能是正确的,因为在美国英语校对中,没有真正的理由强迫任何顺序的西里尔语更好的人。
Common Locale Data Repository为DUCET提供了特定于语言环境的定制。CLDR使用LDML (Locale Data Markup Language,区域数据标记语言)来指定定制,语法由Unicode Technical Specification #35, part 5给出。
CLDR为en_US提供的最新版本的数据没有做任何调整:它使用了一个modified version of the DUCET (正如UTS#35中“根排序规则”下所述)。它在西里尔字母A之后列出了西里尔字母schwa,即您所期望的顺序。
还有一个en_US_POSIX语言环境的数据,其中包括一些修改,但都没有改变任何不在ASCII语言中的东西。
您的系统中安装的en_US语言环境似乎使用了一种定制,将字符放在E的旁边,这可能是因为它们的形式相似。可以说,与将schwa排在A后面相比,给美国英语观众带来的惊喜更少:问人们这是什么,看看有多少人会直接告诉你这是一个“颠倒的E”。这不是对或错,但如果你问我,它似乎比在CLDR中找到的排序规则更合适。
https://stackoverflow.com/questions/16817925
复制相似问题