Unix排序处理下划线字符

时间:2009-07-26 10:54:08

标签: sorting unix environment-variables collation

我有两台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来合并非常大的文件)。

有什么方法可以强制排序以某种方式表现?

感谢。

5 个答案:

答案 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)

差异是由于您locale造成的。使用locale命令检查当前设置。

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