为什么 Gnu 在我的 OSX 机器和 Linux 机器上的排序方式不同?

tre*_*mby 8 linux osx gnu sort locale

我有一台从 coreutils 8.26sort运行 GNU sort(从 Homebrew 安装)的 OSX 机器,以及一台从 coreutils 8.25sort运行 GNU的 Linux 机器sort

在 Mac 上:

mac$ echo -e "{1\n2" | sort
2
{1
Run Code Online (Sandbox Code Playgroud)

在 Linux 上:

linux$ echo -e "{1\n2" | sort
{1
2
Run Code Online (Sandbox Code Playgroud)

我知道这sort取决于语言环境。我locale在 Linux 机器上运行,在每行输出前加上export并在 OSX 机器上运行结果行,然后再次运行(在同一终端中)sort 命令,它给出了与以前相同的输出。

但是,我注意到,locale在 Mac 上运行并没有显示出现在 Linux 上的所有行,我不确定这是否相关。

Linux 上的语言环境:

linux$ locale
LANG=en_CA.UTF-8
LANGUAGE=en_CA:en
LC_CTYPE="en_CA.UTF-8"
LC_NUMERIC="en_CA.UTF-8"
LC_TIME="en_CA.UTF-8"
LC_COLLATE="en_CA.UTF-8"
LC_MONETARY="en_CA.UTF-8"
LC_MESSAGES="en_CA.UTF-8"
LC_PAPER="en_CA.UTF-8"
LC_NAME="en_CA.UTF-8"
LC_ADDRESS="en_CA.UTF-8"
LC_TELEPHONE="en_CA.UTF-8"
LC_MEASUREMENT="en_CA.UTF-8"
LC_IDENTIFICATION="en_CA.UTF-8"
LC_ALL=en_CA.UTF-8
Run Code Online (Sandbox Code Playgroud)

和 OSX 上的语言环境:

mac$ locale
LANG="en_CA.UTF-8"
LC_COLLATE="en_CA.UTF-8"
LC_CTYPE="en_CA.UTF-8"
LC_MESSAGES="en_CA.UTF-8"
LC_MONETARY="en_CA.UTF-8"
LC_NUMERIC="en_CA.UTF-8"
LC_TIME="en_CA.UTF-8"
LC_ALL="en_CA.UTF-8"
Run Code Online (Sandbox Code Playgroud)

我发现如果我LC_ALL=C在两台机器上设置,它们都会2{1. 但是如果我LC_ALL=en_CA.UTF-8在两台机器上设置,我的输出就不同了。如果我LC_ALL=en_CA.utf8在两台机器上设置相同。(在 Linux 机器上locale -a列出en_CA.utf8,但en_CA.UTF-8在 OSX 机器上列出。)

知道这里发生了什么吗?

4ae*_*1e1 5

前几天我对同样的问题做了一些挖掘,所以让我分享一个技术答案。


在 macOS 上,/usr/share/locale/en_US.UTF-8/LC_COLLATE(或en_CA.UTF-8相同的东西)是 的符号链接/usr/share/locale/la_LN.US-ASCII/LC_COLLATE,它是从la_LN.US-ASCII.srcwith生成的colldef。以下是全文la_LN.US-ASCII.src

# ASCII
#
# $FreeBSD: src/share/colldef/la_LN.US-ASCII.src,v 1.2 1999/08/28 00:59:47 peter Exp $
#
order \
    \x00;...;\xff
Run Code Online (Sandbox Code Playgroud)

您可以通过验证校验和来验证二进制LC_COLLATE文件是否确实是从中生成的la_LN.US-ASCII.src

$ colldef -o /dev/stdout usr-share-locale.tproj/colldef/la_LN.US-ASCII.src | sha256sum
9ec9b40c837860a43eb3435d7a9cc8235e66a1a72463d11e7f750500cabb5b78  -

$ sha256sum </usr/share/locale/en_US.UTF-8/LC_COLLATE
9ec9b40c837860a43eb3435d7a9cc8235e66a1a72463d11e7f750500cabb5b78  -
Run Code Online (Sandbox Code Playgroud)

该规则集很容易理解:只需将字节值一一比较即可。因此,排序规则en_US.UTF-8与 POSIX 语言环境(又名 C 语言环境)相同。{是 0x7B,2是 0x32,所以{在 后面2

该规则集是 FreeBSD 5 的产物,已同步到 Mac OS X 10.3 Panther 中。请参阅colldefFreeBSD 5.0.0 源代码树中的目录。从那时起,它在 OS X / macOS 上就再也没有改变过。


在 Linux 上,区域设置程序和数据是glibc. 请参阅 glibclocaledata/locales,或/usr/share/i18n/locales在 Debian/Ubuntu 上。如果您检查/usr/share/i18n/locales/en_US,您会发现它符合iso14651_t1_common规则LC_COLLATE。因此它遵循ISO 14651规则进行排序。


博文中有更多详细信息:https ://blog.zhimingwang.org/macos-lc_collat​​e-hunt 。