Linux

為什麼 Gnu 在我的 OSX 機器和 Linux 機器上排序不同?

  • June 6, 2020

我有一台從 coreutils 8.26(從 Homebrew 安裝)sort執行 GNU的 OSX 機器,還有一台從 coreutils 8.25執行 GNU的 Linux 機器。sort``sort``sort

在 Mac 上:

mac$ echo -e "{1\n2" | sort
2
{1

在 Linux 上:

linux$ echo -e "{1\n2" | sort
{1
2

我知道這sort取決於語言環境。我locale在 Linux 機器上執行,在每行輸出前面加上export並在 OSX 機器上執行結果行,然後再次執行(在同一個終端中)排序命令,它給出了與以前相同的輸出。

然而,我注意到,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

和 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"

我發現如果我LC_ALL=C在兩台機器上都設置,它們都排2{1. 但是,如果我LC_ALL=en_CA.UTF-8在兩台機器上都設置,我會得到與上面不同的輸出。如果我LC_ALL=en_CA.utf8在兩台機器上都設置相同。(Linux 機器上的locale -a列表,但OSX 機器上的列表。)en_CA.utf8``en_CA.UTF-8

知道這裡發生了什麼嗎?

前幾天我對同樣的問題進行了一些探勘,所以讓我分享一個技術答案。


在 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

您可以通過驗證校驗和來驗證二進製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  -

規則集很容易理解:只需一一比較字節值。因此,排序規則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 。

引用自:https://unix.stackexchange.com/questions/362728