comm命令给出错误的输出?

时间:2017-09-15 00:58:06

标签: shell unix comm

我有两个文件,每行只列出一堆不同的文件名。我合并了它们,对它们进行了排序,然后检查了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进行比较时,数字是正确的。

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

EDIT1:

$ 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

EDIT2:

由于评论中的一些建议,经过一些更多的调查后,似乎问题可能是由于commsort工具的版本控制。

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

在Linux框中,commsort都来自2012年1月的GNU coreutils 8.4,并且调用工作正常。

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

1 个答案:

答案 0 :(得分:1)

要使comm起作用,需要对其输入进行排序。它需要与您的sort一致,了解要使用的排序方法。在C语言环境(LC_ALL=C)中,这很容易。字符串一次比较一个字节,并且不同的第一个字节决定顺序。

en_US.UTF-8语言环境中,它更难。首先,没有单一的权威机构描述预期的行为到底是什么。每个供应商都可以自由地想象"英语排序顺序,美国变体"手段。然后记录该决定与否(通常他们选择"不是")。当你的工具是BSD的一半,一半来自GNU时,分歧的机会增加了(虽然从理论上讲,我认为它们都应该遵循本地C库...)

使用LC_ALL=C运行所有命令会使他们更有可能彼此达成一致。