You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何LANG=en_US.UTF-8时GNU comm命令无法区分✓与⨯?

为何UTF-8环境下GNU comm无法区分两个文件的内容?

问题背景

我有两个文件:

  • a.txt内容:
meow ✓ bar
  • b.txt内容:
meow ⨯ bar

执行不同LANG设置下的comm命令,结果差异明显:

LANG=C时的输出

$ LANG=C comm a.txt b.txt
meow ✓ bar
    meow ⨯ bar

LANG=en_US时的输出

$ LANG=en_US comm a.txt b.txt
meow ✓ bar
    meow ⨯ bar

LANG=en_US.UTF-8时的输出

$ LANG=en_US.UTF-8 comm a.txt b.txt
        meow ⨯ bar

补充的文件字节码输出(od -c):

$ od -c a.txt
0000000   m   e   o   w     342 234 223       b   a   r  \n
0000015

$ od -c b.txt
0000000   m   e   o   w     342 250 257       b   a   r  \n
0000015

原因分析

comm命令的核心行为完全依赖当前系统的locale排序规则,且要求输入文件必须提前按对应规则完成排序,否则输出结果无意义。

  1. C locale(或非UTF-8 locale)的情况
    当LANG=C时,系统采用严格字节序排序——直接比较字符的ASCII/字节值。a.txt中的✓(UTF-8字节为0xE2 0x9C 0x83)和b.txt中的⨯(UTF-8字节为0xE2 0xA8 0xAF)字节序列完全不同,因此两行被判定为不同内容。同时因为这两行的字节序本身是a在前、b在后,符合C locale的排序顺序,所以comm能正确区分。

  2. UTF-8 locale的情况
    当LANG=en_US.UTF-8时,系统使用针对UTF-8设计的排序规则,这类规则会对非字母数字的符号做特殊处理:要么忽略符号的差异,要么给部分符号赋予相同的排序权重。这里的✓和⨯都属于符号类,在排序时被视为等价内容,导致comm认为两行完全相同。
    另外,你没有提前用LANG=en_US.UTF-8 sort对文件排序,这进一步放大了结果的异常——comm的设计逻辑就是基于“输入已按当前locale排序”的前提,未排序的输入会导致错误的匹配判定。

验证方法

如果按对应locale先排序文件再执行comm,就能看到明确的差异:

  • UTF-8 locale下排序后执行comm:
LANG=en_US.UTF-8 sort a.txt > a_sorted.txt
LANG=en_US.UTF-8 sort b.txt > b_sorted.txt
LANG=en_US.UTF-8 comm a_sorted.txt b_sorted.txt

此时两行会被判定为共同行,因为排序规则将它们视为等价。

  • C locale下排序后执行comm:
LANG=C sort a.txt > a_sorted.txt
LANG=C sort b.txt > b_sorted.txt
LANG=C comm a_sorted.txt b_sorted.txt

结果会和直接执行LANG=C comm一致,两行被明确区分。

内容的提问来源于stack exchange,提问作者binaryfunt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:10:02