為什麼 Gnu 在我的 OSX 機器和 Linux 機器上排序不同?
我有一台從 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.src
with生成的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。請參閱
colldef
FreeBSD 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_collate-hunt 。