ɛ
(“拉丁字母epsilon”)是某些非洲语言中使用的字母,通常代表英语“ bed”中的元音。在Unicode中,它的编码为U + 025B,与日常的非常不同e
。
但是,如果我sort
以下内容:
eb
ed
ɛa
ɛc
似乎sort
考虑ɛ
和e
等效:
ɛa
eb
ɛc
ed
这里发生了什么?而且是有办法让ɛ
和e
独特的sort
荷兰国际集团的目的呢?
ea
混合ɛa
并排序。您将看到它总是ea
在之前排序ɛa
。因此,不,它们不被视为相等。
ɛ
(“拉丁字母epsilon”)是某些非洲语言中使用的字母,通常代表英语“ bed”中的元音。在Unicode中,它的编码为U + 025B,与日常的非常不同e
。
但是,如果我sort
以下内容:
eb
ed
ɛa
ɛc
似乎sort
考虑ɛ
和e
等效:
ɛa
eb
ɛc
ed
这里发生了什么?而且是有办法让ɛ
和e
独特的sort
荷兰国际集团的目的呢?
ea
混合ɛa
并排序。您将看到它总是ea
在之前排序ɛa
。因此,不,它们不被视为相等。
Answers:
不,它不认为它们是等效的,它们具有相同的主要权重。这样一来,它们近似排序。
如果您在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
具有相同的主要权重e
和E
相同的次级权重,只有第三权重可以区分它们。
比较字符串时sort
(strcoll()
标准libc函数用于比较字符串)从比较所有字符的主要权重开始,并且仅在字符串与主要权重相等(以此类推)与其他权重相等时才选择第二个权重。
在这种情况下,按近似排序的顺序似乎忽略了大小写。Ab
之间的种种aa
和ac
,但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语言环境中,它会变得更糟,因为有成千上万没有排序顺序,并最终排序相同的字符,造成各种问题(如破comm
,join
,ls
或具有不确定性令水珠... ),因此建议您使用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%),与其他字符的排序方式相同(未定义其排序顺序)。
也可以看看:
<PCL>
?其他似乎是资本,微不足道和基本的?
ea
然后ɛa
将它们混合在一起,我们将看到sort
所有ea
s在ɛa
s 之前排序。
strcoll()
,请参见编辑。
男子排序:
*** 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
LC_ALL
为空,则sort
可以使用其他LC_*
变量LANG
或某些配置文件。
LC_COLLATE
是特定于字符串排序的,LANG
是非常普通的一种。
字符ɛ不等于e,但是某些语言环境在整理时可以将这些符号聚集在一起。其原因是特定于语言的,但也有一定的历史甚至政治背景。例如,大多数人可能期望€uro货币在字典中接近欧洲。
无论如何,要查看您当前正在使用哪种排序规则locale
,locale -a
它将为您提供系统上可用的语言环境列表,并将排序规则更改为C
仅用于一次排序运行LC_COLLATE=C sort file
。最后看看不同的语言环境如何对文件进行排序
for loc in $(locale -a)
do echo ____"${loc}"____
LC_COLLATE="$loc" sort file
done
将结果通过管道传递到某些grepp工具,以选择适合您需要的语言环境。
ea
在文件中添加一条普通行,然后在输出中sort -u
同时获得ea
和ɛa
。最好的策略是避免(export LC_COLLATE=C
)。否则,将会发生许多丑陋的事情(例如/tmp/[a-z]
in bash
将匹配/tmp/a
,/tmp/A
但不会/tmp/Z
)。
fnmatch()
和regexp范围内进行修复,但不能通过bash
使用本身实现其范围的类似方式进行修复strcoll()
。ksh93从来没有问题,因为它的范围实现使用strcoll()
并且还检查范围末尾的大小写,并且如果两端均为小写,则仅匹配小写字符。zsh范围没有问题,因为它是基于代码点而不是strcoll()完成的。