26

我有两台 linux 机器,其中 unix 排序似乎表现不同。我相信我已经将其范围缩小到下划线字符的处理。

如果我运行sort tmp,其中 tmp 包含以下两行:

aa_d_hh
aa_dh_ey

一台机器输出

aa_d_hh
aa_dh_ey

(即“_”在“h”之前)而其他输出

aa_dh_ey
aa_d_hh

(即“h”在“_”之前)。我需要这些机器一起运行(因为我稍后使用 sort -m 来合并非常大的文件)。

有什么方法可以强制排序以一种或另一种方式表现吗?

谢谢。

4

5 回答 5

38

您可以LC_COLLATE仅为您的命令设置传统的排序顺序:

env LC_COLLATE=C sort tmp

这不会改变当前环境,只是改变排序命令执行的环境。您应该对此具有相同的行为。

于 2009-07-26T11:28:33.960 回答
7

这可能是由于语言环境的差异造成的。在en_US.UTF-8语言环境中,下划线 ( _) 在字母和数字之后排序,而在POSIXC语言环境中,它们在大写字母和数字之后排序,但小写字母之前。

# won't change LC_COLLATE=C after execution
$ LC_COLLATE=C sort filename

您还可以sort --debug用于显示有关一般排序行为的更多信息:

$ (echo 'foo_bar'; echo 'fooAbar'; echo 'foo0bar'; echo 'fooabar') |
      LC_COLLATE=en_US.UTF-8 sort --debug
sort: using ‘en_US.UTF-8’ sorting rules
foo0bar
fooabar
fooAbar
foo_bar

$ (echo 'foo_bar'; echo 'fooAbar'; echo 'foo0bar'; echo 'fooabar') | 
      LC_COLLATE=C sort --debug
sort: using simple byte comparison
foo0bar
fooAbar
foo_bar
fooabar

也如this answer所示,您可以使用上述公式强制LC_COLLATE=C执行单个命令,而无需修改您的shell环境:

于 2017-03-28T23:30:53.760 回答
4

排序顺序取决于环境变量 LC_COLLATE 的当前值。检查您的本地文档以获取“locale”、“setlocale”等。在两台机器上将 LC_COLLATE 设置为“POSIX”,结果应该匹配。

于 2009-07-26T11:07:59.400 回答
3

我真的很喜欢上面这个有用示例的答案,我只需在其列表中添加另一个字符串以显示排序行为有多奇怪:

$ (echo 'foo_bar'; echo 'fooAbar'; echo 'foo0bar'; echo 'fooabar'; echo 'foobbar'; echo 'foobar') | LC_COLLATE=en_US.UTF-8 sort --debug
sort: using ‘en_US.UTF-8’ sorting rules
foo0bar
_______
fooabar
_______
fooAbar
_______
foobar
______
foo_bar
_______
foobbar
_______

看起来很疯狂吧?在这里找到了解释,在这种情况下,这是因为在这个语言环境中使用了 unicode 排序算法: https ://unix.stackexchange.com/questions/252419/unexpected-sort-order-in-en-us-utf-8 -语言环境

然而,即使是 ' sort --debug ' 选项也不能轻易地展示strcoll () 函数遵守区域排序规范的规则的微妙之处。

POSIX 规定语言环境作者(除 C 语言环境之外的所有语言环境)对strcoll () 行为方式的各种繁琐方面具有绝对控制权,并且两家供应商声明其语言环境名为 en_US.UTF-8的事实并不意味着/要求这两个供应商具有相同的语言环境定义。因此,两个不同平台之间的排序规则很可能是不同的,这取决于为该平台编写语言环境文件的人,以及随着时间的推移将哪些错误修复合并到语言环境定义中。

感谢 Red Hat 的 Eric Blake 提供这一见解。

于 2020-04-10T11:37:43.257 回答
0

差异是由于您的语言环境。使用locale命令检查当前设置。

有许多不同的语言环境类别,例如LC_COLLATELC_TIMELC_MESSAGESLC_ALL您可以通过设置环境变量或来更改它们LANG,或者通过设置环境变量来仅更改排序(排序)顺序LC_COLLATE。locale CorPOSIX是标准定义的基本语言环境;其他包括en_US(美国英语)、fr_FR(法语)等。

于 2009-07-26T11:26:53.683 回答