我有一个包含UTF-8编码文本行的文本文件:
mac-os-x$ cat unsorted.txt
ウ
foo
チ
'foo'
津
如果它有助于重现问题,这里有一个校验和和文件中确切字节的转储,以及如何自己生成文件(在Linux上,使用base64 -d
代替{ {1}}):
-D
当我在Mac OS X上对此输入文件进行排序时(无论我使用的是Mac OS X Yosemite附带的GNU sort 5.93,还是使用Homebrew安装的GNU排序版本8.23),我得到了这个排序结果:
mac-os-x$ shasum unsorted.txt
a6d0b708d3e0cafb0c6e1af7450e9243da8cb078 unsorted.txt
mac-os-x$ perl -ne 'print join(" ", map { sprintf "%02x", ord } split //), "\n"' unsorted.txt
e3 82 a6 0a
66 6f 6f 0a
e3 83 81 0a
27 66 6f 6f 27 0a
e6 b4 a5 0a
mac-os-x$ echo 44KmCmZvbwrjg4EKJ2ZvbycK5rSlCg== | base64 -D > unsorted.txt
当我使用相同的语言环境设置对同一文件进行排序时,在Linux上(我在Centos 5.5和CentOS 6.5上进行了测试),我得到了不同的结果:
mac-os-x$ env -i LANG=en_US.utf-8 LC_ALL=en_US.utf-8 /usr/bin/sort unsorted.txt
'foo'
foo
ウ
チ
津
mac-os-x$ echo `sw_vers -productName` `sw_vers -productVersion`
Mac OS X 10.10.1
mac-os-x$ /usr/bin/sort --version | head -1
sort (GNU coreutils) 5.93
请注意日语假名与英语的不同位置,以及两行之间的不同排序顺序,只有单引号不同。
为了在混音中添加另一个变体,我注意到在我拥有的一个非常旧的FreeBSD 6盒子上,我获得了与OS X相同的排序顺序:
linux-centos-6.5$ env -i LANG=en_US.utf-8 LC_ALL=en_US.utf-8 /bin/sort unsorted.txt
ウ
チ
foo
'foo'
津
linux-centos-6.5$ cat /etc/redhat-release
CentOS release 6.5 (Final)
linux-centos-6.5$ /bin/sort --version | head -1
sort (GNU coreutils) 8.4
我希望排序顺序在每种情况下都相同,因为所有情况都使用GNU排序,所有情况都使用相同的区域设置。我尝试单独设置freebsd-6.0$ env -i LANG=en_US.utf-8 LC_ALL=en_US.utf-8 /usr/bin/sort unsorted.txt
'foo'
foo
ウ
チ
津
freebsd-6.0$ uname -rs
FreeBSD 6.0-RELEASE
freebsd-6.0$ sort --version | head -1
sort (GNU coreutils) 5.3.0-20040812-FreeBSD
,并尝试使用LC_COLLATE
强制按字节顺序排序,但这并没有改变任何结果。
为什么我的示例输入文件在OS X和Linux中的排序方式不同?我怎么能强迫两个系统生成相同排序的文本(我不关心哪个变体,只要它们在两者之间是一致的)?
答案 0 :(得分:1)
看起来 - 你的linux sort
没有保留正确的UTF-8顺序。
您unsorted.txt
(首字母)的十六进制UTF-8表示形式为:
ウ - 30A6
foo - 0066
チ - 30C1
'foo' - 0027
津 - 6D25
取自http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=%E3%82%A6&mode=char
因此,根据unicode整理(http://www.unicode.org/Public/UCA/latest/allkeys.txt)进行正确排序将是:
'foo' - 第487行
foo - 第8966行
ウ - 第20875行
チ - 第21004行
津 - 不在档案
所以,为了回答你的问题,你的linux机器为sort
函数提供了错误的校对表。不幸的是,我无法分辨出可能的原因。
PS:与你的here有类似的问题。
修改强>
正如@ninjalj所注意到的,glibc不使用UCA,而是使用ISO-14651。 This bug report建议迁移到UCA。不幸的是,它仍未解决。
此外,它可能以某种方式与MacOSX上的question about ls case insensivity相关联。有些人甚至认为它与HFS文件系统有关。