为什么 sort 说 ɛ = e?

为什么 sort 说 ɛ = e?

ɛ(“拉丁 epsilon”)是某些非洲语言中使用的字母,通常代表英语“bed”中的元音。在 Unicode 中,它的编码为 U+025B,与日常使用的非常不同e

但是,如果我sort执行以下操作:

eb
ed
ɛa
ɛc

看来sort考虑ɛe等价:

ɛa
eb
ɛc
ed

这里发生了什么?有没有办法使ɛe区分 为sorting 目的?

答案1

不,它并不认为它们是等效的,它们只是具有相同的主要权重。因此,在初步近似中,它们的排序是相同的。

如果您在 GNU 系统(此处使用 glibc 2.27)上查看 /usr/share/i18n/locales/iso14651_t1_common (用作大多数语言环境的基础),您将看到:

<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U025B> <e>;<PCL>;<MIN>;IGNORE # 287 ɛ
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E

eɛ并且E具有相同的主要权重eE相同的次要权重,只有第三个权重区分它们。

比较字符串时,sortstrcoll()标准 libc 函数用于比较字符串)首先比较所有字符的主要权重,只有当字符串与主要权重相等时才比较第二个权重(与其他权重依此类推) 。

这就是在第一次近似排序中忽略大小写的方式。在和Ab之间排序,但可以根据语言规则排序在之前或之后(某些语言在之前,如英国英语,有些在之前,如爱沙尼亚语)。aaacAbab<MIN><CAP><CAP><MIN>

如果e与 具有相同的排序顺序ɛprintf '%s\n' e ɛ | sort -u则仅返回一行。但正如<BAS>之前所说<PCL>e单独排序 ɛeɛe排序在EEE(在第二权重)之后,即使EEE排序在eee(为此我们需要上升到第三权重)。

现在,如果在我的系统上使用 glibc 2.27,我运行:

sed -n 's/\(.*;[^[:blank:]]*\).*/\1/p' /usr/share/i18n/locales/iso14651_t1_common |
  sort -k2 | uniq -Df1

您会注意到,有相当多的字符是用完全相同的 4 个权重定义的。特别是,我们的 ɛ 具有相同的权重:

<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE

果然:

$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
ǝ
$ expr ɛ = ǝ
1

这可以看作是 GNU libc 语言环境的一个错误。在大多数其他系统上,区域设置确保所有不同的字符最终具有不同的排序顺序。在 GNU 语言环境中,情况变得更糟,因为有数千个字符没有排序顺序,最终排序相同,导致各种问题(例如破坏comm, join,ls具有不确定顺序的 glob... ),因此建议使用LC_ALL=C解决这些问题

正如 @ninjalj 在评论中指出的,2018 年 8 月发布的 glibc 2.28 在这方面进行了一些改进,尽管 AFAICS 仍然存在一些使用相同排序顺序定义的字符或整理元素。在使用 glibc 2.28 且语言环境为 en_GB.UTF-8 的 Ubuntu 18.10 上。

$ expr $'L\ub7' = $'L\u387'
1

L(为什么只有与/组合时 U+00B7 才被认为与 U+0387 等效l?!)。

和:

$ perl -lC -e 'for($i=0; $i<0x110000; $i++) {$i = 0xe000 if $i == 0xd800; print chr($i)}' | sort > all-chars-sorted
$ uniq -d all-chars-sorted | wc -l
4
$ uniq -D all-chars-sorted | wc -l
1061355

(仍然有超过 100 万个字符(Unicode 范围的 95%,低于 2.27 中的 98%)与其他字符的排序相同,因为它们的排序顺序未定义)。

也可以看看:

答案2

男人排序:

   ***  WARNING  ***  The locale specified by the environment affects sort
   order.  Set LC_ALL=C to get the traditional sort order that uses native
   byte values.

所以,尝试:LC_ALL=C sort file.txt

答案3

字符 ɛ 不等于 e,但某些语言环境可以在整理时将这些符号聚集在一起。其原因是特定于语言的,但也有一定的历史甚至政治背景。例如,大多数人可能期望欧元货币接近欧洲在字典中。

无论如何,要查看当前运行时使用的排序规则locale,它将locale -a为您提供系统上可用的区域设置列表,并将排序规则更改为C仅用于一次排序运行LC_COLLATE=C sort file。最后看看不同的语言环境如何对文件进行排序尝试

for loc in $(locale -a)
    do echo ____"${loc}"____
    LC_COLLATE="$loc" sort file
done

将结果通过管道传输到某个 grep 工具,以选择适合您需要的区域设置。

相关内容