异常排序规则导致comm、sort、ls等命令输出错误该如何排查解决
问题根因
排序异常本质是系统文本排序规则不匹配导致的,哪怕两台机器的LC_*、LANG环境变量完全一致,也可能因为以下几个底层差异出现问题:
- 系统locale定义文件版本不一致:不同发行版、同发行版不同补丁版本的
en_GB.UTF-8locale的排序规则(collate规则)可能存在差异,部分旧版本的locale规则会默认忽略英文大小写、忽略标点符号进行排序,才会出现大小写混排、下划线和点的排序顺序不符合预期的问题。 - 命令版本差异:
sort属于coreutils包,不同版本的coreutils对排序规则的实现逻辑存在差异,部分旧版本的实现存在兼容性bug。 - 命令别名覆盖:系统可能配置了
sort或者ls的别名(比如给sort加了-f忽略大小写的参数,给ls加了--ignore-case的参数),优先级高于默认命令。 - 系统级locale配置覆盖:
/etc/locale.conf、/etc/default/locale或者shell配置文件(.bashrc、.zshrc等)可能存在未被env命令打印的隐式区域配置,或者有强制修改LC_COLLATE的逻辑。
排查步骤
- 先排查命令别名:执行
type sort和type ls,确认返回的是系统默认的二进制文件路径,而非alias。如果是别名,检查shell配置文件里的别名定义。 - 强制指定C locale测试排序结果:执行下面的命令,看排序是否符合预期,C locale会按ASCII码值原生排序,不会做特殊规则处理:
# 测试sort printf 'G.EC\nGE.BO\nGE.DA\n' | LC_COLLATE=C sort # 测试ls排序 LC_COLLATE=C ls
如果指定C locale后排序正常,就可以确认是当前使用的locale排序规则不符合预期。
3. 对比两台机器的coreutils版本:执行sort --version看版本号是否一致,版本差过大的话大概率是实现逻辑差异。
4. 对比两台机器的locale定义:执行locale -a | grep en_GB.utf8确认locale存在,再执行localedef --list-archive | grep en_GB看locale编译后的版本是否一致,也可以直接对比/usr/lib/locale/目录下的对应locale文件的大小和修改时间。
解决方法
- 临时解决:如果只是单次执行命令需要正确排序,可以在命令前临时指定
LC_COLLATE为C,比如:
# 让comm按ASCII排序对比 LC_COLLATE=C comm a.txt b.txt # 让ls按ASCII排序输出 LC_COLLATE=C ls
- 永久解决:
- 如果是别名问题,删除shell配置文件中对应的
sort/ls别名即可 - 如果是coreutils版本问题,将出问题机器的coreutils包升级到和正常机器一致的版本
- 如果是locale规则问题,可以在用户shell配置文件(
~/.bashrc、~/.zshrc等)中加入export LC_COLLATE=C,强制所有命令的排序规则使用ASCII排序,修改后执行source ~/.bashrc生效。如果需要全局生效,把配置加到/etc/profile或者/etc/locale.conf中即可。
- 如果是别名问题,删除shell配置文件中对应的
内容的提问来源于stack exchange,提问作者wsdzbm
相关产品推荐
相关产品推荐

