comm 命令给出了错误的输出?

comm command gives faulty output?

我有两个文件,每行列出一堆不同的文件名。我合并它们,对它们进行排序,然后检查 comm 输出并发现一些非常有趣的东西。

$ sort -u -o list1 list1
$ sort -u -o list2 list2
$ cat list1 list2 > combined
$ wc -l list1 
  18141 list1
$ wc -l list2 
  21755 list2
$ wc -l combined 
  39896 combined
$ sort -u -o combined combined 
$ wc -l combined 
  24400 combined


$ comm -23 list1 combined | wc -l
  12889
$ comm -13 list1 combined | wc -l
  19148
$ comm -12 list1 combined | wc -l
   5252


$ comm -23 list2 combined | wc -l
      0
$ comm -13 list2 combined | wc -l
   2645
$ comm -12 list2 combined | wc -l 
  21755

(为清楚起见,上面换行)

最后几次调用 comm 是怎么回事?当我将 list1combined 进行比较时,输出很古怪,但是当我将 list2combined 进行比较时,输出似乎很好。

我什至尝试再次组合所有三个列表并测试:

$ cat list1 list2 combined > combined-again
$ wc -l combined-again 
  64296 combined-again
$ sort -u -o combined-again combined-again
$ wc -l combined-again 
  24400 combined-again
$ diff combined combined-again

combinedcombined-again 的排序唯一行数匹配,diff!

没有输出
$ comm combined combined-again | wc -l
  24400
$ comm -12 combined combined-again | wc -l
  24400
$ comm -3 combined combined-again | wc -l
      0

这些 comm 输出是有意义的,两个文件之间应该没有任何区别。

$ comm -23 list1 combined-again | wc -l
  12889
$ comm -13 list1 combined-again | wc -l
  19148
$ comm -12 list1 combined-again | wc -l
   5252

list1 进行比较时,我们再次看到相同的不稳定数字。

$ comm -23 list2 combined-again | wc -l                     
      0
$ comm -13 list2 combined-again | wc -l
   2645
$ comm -12 list2 combined-again | wc -l
  21755

list2 比较时,数字是适当且正确的。

对于combined-again中的那些行,我什至使用了从comm -23 list1 combined-againgrep的一些输出行,这些行确实存在。我完全不知道为什么 comm 在这种情况下输出有问题...

编辑 1:

$ locale
  LANG="en_US.UTF-8"
  LC_COLLATE="en_US.UTF-8"
  LC_CTYPE="en_US.UTF-8"
  LC_MESSAGES="en_US.UTF-8"
  LC_MONETARY="en_US.UTF-8"
  LC_NUMERIC="en_US.UTF-8"
  LC_TIME="en_US.UTF-8"
  LC_ALL=

每个文件都不包含奇怪的符号或字符,只是使用驼峰式大小写的包名。例如:

$ head list1
  AAAAuthentication
  AAACorrelationAPI
  AAACorrespondence
  AAATestSuite
  AESDescription
  AESImplementation
  AESLogging
  AESMaster
  AESProofSystem
  AESTestSuite

编辑 2:

根据评论中的一些建议进行更多调查后,问题似乎可能是由于 commsort 工具的版本控制所致。

I 运行 mac 上的所有上述命令,其中 comm 来自 BSD 2005 年 1 月 26 日,sort 来自 GNU coreutils,排序 5.93 2005 年 11 月。

在 linux 框中,commsort 均来自 2012 年 1 月的 GNU coreutils 8.4,并且调用完美无缺。

我想现在的问题是:版本之间的差异是什么,为什么会影响 comm 输出,如上所示?

要使 comm 正常工作,需要对其输入进行排序。它需要同意你的 sort 使用什么排序方法。在 C 语言环境 (LC_ALL=C) 中这很容易。字符串一次比较一个字节,第一个不同的字节决定顺序。

en_US.UTF-8 语言环境中,这更难。首先,没有单一的权威来描述预期的行为到底是什么。每个供应商都可以自由想象 "English sort order, US variant" 意味着什么。然后记录该决定与否(通常他们选择 "not")。当您的工具一半来自 BSD,一半来自 GNU 时,出现分歧的机会就会增加(尽管从理论上讲,我认为它们都应该遵从本地 C 库...)

运行 你所有带有 LC_ALL=C 的命令应该会让它们更容易达成一致。