我有两台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来合并非常大的文件)。
有什么方法可以强制排序以某种方式表现?
感谢。
答案 0 :(得分:26)
您可以将LC_COLLATE
设置为传统的排序顺序,仅用于您的命令:
env LC_COLLATE=C sort tmp
这不会改变当前环境只是执行sort命令的环境。 你应该对此有相同的行为。
答案 1 :(得分:4)
排序顺序取决于环境变量LC_COLLATE的当前值。检查本地文档中的'locale','setlocale'等。在两台机器上将LC_COLLATE设置为'POSIX',结果应匹配。
答案 2 :(得分:2)
这可能是由于语言环境的差异造成的。在en_US.UTF-8
区域设置中,下划线(_
)按字母和数字排序,而在POSIX C
locale中它们按大写字母和数字排序,但在小写数字之前排序
# 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环境:
答案 3 :(得分:1)
我真的很喜欢上面给出有用示例的答案,我只是将另一个字符串添加到其列表中,以显示排序行为可能有多么奇怪:
$ (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-locale
但是,即使' sort --debug '选项也无法轻松演示 strcoll ()函数遵循语言环境排序的规则中的细微差别规范。
POSIX规定,语言环境作者(除C语言环境以外的所有语言环境)都对 strcoll ()行为的各种摆弄方式具有绝对控制权,并且两个供应商声明其语言环境是命名 en_US.UTF-8 确实 不 暗示/ 要求这两个供应商具有相同的语言环境定义。 因此,两个不同平台之间的排序规则很可能会有所不同,这取决于谁为该平台编写了语言环境文件,并且随着时间的推移,哪些错误修复程序已合并到语言环境定义中。
感谢Red Hat的Eric Blake的见解。
答案 4 :(得分:0)