sort为什么这么说?= ?

Dra*_*nis 27 sort unicode locale

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

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

eb
ed
?a
?c
Run Code Online (Sandbox Code Playgroud)

似乎sort考虑?e等效:

?a
eb
?c
ed
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?有没有一种方法可以为ing 目的制作?e区分sort

Sté*_*las 68

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

如果您查看 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE
Run Code Online (Sandbox Code Playgroud)

果然:

$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
?
$ expr ? = ?
1
Run Code Online (Sandbox Code Playgroud)

这可以看作是 GNU libc 语言环境的错误。在大多数其他系统上,语言环境确保所有不同的字符最终具有不同的排序顺序。在GNU语言环境中,它会变得更糟,因为有成千上万没有排序顺序,并最终排序相同的字符,造成各种问题(如破commjoinls或具有不确定性令水珠... ),因此建议使用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
Run Code Online (Sandbox Code Playgroud)

(为什么 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
Run Code Online (Sandbox Code Playgroud)

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

也可以看看:

  • 这正是我要找的!为了完整起见,`&lt;PCL&gt;` 代表什么?其他的似乎是 Capital、Miniscule 和 Basic? (3认同)
  • @Draconis, _collat​​ing-symbol &lt;PCL&gt; # 16 特殊/特殊_ (3认同)
  • 从 glibc 2.28 开始,代码点应该用作第 4 级权重的后备,请参阅 https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=bc1d41044c0cf9f0214acdbfd79b6cd11fd1e8c1 https://sourceware.org/git/gitweb.cgi?p=glibc.git sourceware.org/bugzilla/show_bug.cgi?id=14095 (2认同)

Ipo*_*cer 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.
Run Code Online (Sandbox Code Playgroud)

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

  • @Draconis 如果`LC_ALL` 为空,`sort` 可能会使用其他`LC_*` 变量、`LANG` 或一些配置文件。 (3认同)

jim*_*mij 8

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

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

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

将结果传送到一些 gring 工具以选择适合您需要的语言环境。


归档时间:

查看次数:

4367 次

最近记录:

7 年 前