为什么排序说ɛ= e?


25

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

但是,如果我sort以下内容:

eb
ed
ɛa
ɛc

似乎sort考虑ɛe等效:

ɛa
eb
ɛc
ed

这里发生了什么?而且是有办法让ɛe独特的sort荷兰国际集团的目的呢?


21
排序规则称为“整理”,如果可以帮助您进行谷歌搜索
BlueRaja-Danny Pflughoeft 18-10-26

1
尝试在文本文件中放入一定数量的ea混合ɛa并排序。您将看到它总是ea在之前排序ɛa。因此,不,它们不被视为相等。
巴库里

可能是显而易见的一点,但是我还没有看到它的明确建议:如果您要对$(certain_african_language)中的单词进行排序,自然要做的就是将语言环境设置为$(certain_african_language)。
Federico Poloni

@FedericoPoloni一个非常好的观点!不幸的是,我找不到该语言的语言环境。
Draconis

1
@GermánBouzas这是专门用于与拉丁字母匹配的形式“拉丁epsilon”。它们看起来几乎相同,但拉丁字母为U + 025B,而希腊字母为U + 03B5。
Draconis '18年

Answers:


67

不,它不认为它们是等效的,它们具有相同的主要权重。这样一来,它们近似排序。

如果您在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之间的种种aaac,但Ab可以排序之前或之后ab根据语言规则(有些语言有<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语言环境中,它会变得更糟,因为有成千上万没有排序顺序,并最终排序相同的字符,造成各种问题(如破commjoinls或具有不确定性令水珠... ),因此建议您使用LC_ALL=C这些问题

正如@ninjalj在评论中指出的那样,2018年8月发布的glibc 2.28通过AFAICS在这方面进行了一些改进,仍然有一些字符或排序元素定义了相同的排序顺序。在具有glibc 2.28的Ubuntu 18.10和en_GB.UTF-8语言环境中。

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

(为什么仅将U + 00B7与L/ ?!组合才视为与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%),与其他字符的排序方式相同(未定义其排序顺序)。

也可以看看:


3
这正是我想要的!为了完整性,代表什么<PCL>?其他似乎是资本,微不足道和基本的?
Draconis '18

3
@Draconis,核对符号<PCL>#16 particulier /奇特
斯特凡Chazelas

的确,如果我们将一堆文件混合在一起,ea然后ɛa将它们混合在一起,我们将看到sort所有eas在ɛas 之前排序。
巴库里

2
从glibc的2.28,码点应作为备用的4级重量,看sourceware.org/git/... sourceware.org/bugzilla/show_bug.cgi?id=14095
ninjalj

1
@cat,对不起,我的意思是strcoll(),请参见编辑。
斯特凡Chazelas

15

男子排序:

   ***  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


1
这样可行!但是,为什么默认语言环境将这些完全独立的代码点视为相同?我很好奇为什么会这样。
Draconis

@Draconis什么是“默认语言环境”?
卡米尔Maciorowski

@KamilMaciorowski环境变量的空值;我不确定对应的语言环境。
Draconis

3
@Draconis如果LC_ALL为空,则sort可以使用其他LC_*变量LANG或某些配置文件。
NieDzejkob

1
LC_COLLATE是特定于字符串排序的,LANG是非常普通的一种。
ShadowRanger

8

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

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

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

将结果通过管道传递到某些grepp工具,以选择适合您需要的语言环境。


这是一个很好的解释,但是这些符号似乎被认为是相同的,而不仅仅是彼此靠近。
Draconis

1
不,它们不被视为相同。ea在文件中添加一条普通行,然后在输出中sort -u同时获得eaɛa。最好的策略是避免export LC_COLLATE=C)。否则,将会发生许多丑陋的事情(例如/tmp/[a-z]in bash将匹配/tmp/a/tmp/A但不会/tmp/Z)。
mosvy

@mosvy呵呵,有趣的是...所以出于订购目的,它们是相同的,但出于唯一性目的,它们不是吗?
Draconis

他们被认为是不同的。看到这里的解释。
mosvy

1
@ninjalj,可以在glibc fnmatch()和regexp范围内进行修复,但不能通过bash使用本身实现其范围的类似方式进行修复strcoll()。ksh93从来没有问题,因为它的范围实现使用strcoll()并且还检查范围末尾的大小写,并且如果两端均为小写,则仅匹配小写字符。zsh范围没有问题,因为它是基于代码点而不是strcoll()完成的。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.