2

我有两个文件,它们只是在每一行上列出了一堆不同的文件名。我将它们合并,排序,然后检查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?当我比较list1输出combined时很古怪,但是当我比较list2输出时combined似乎很好。

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

$ 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-againto的一些输出行来grep表示 中的那些行combined-again,并且这些行确实存在。我完全不知道为什么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工具的版本控制。

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

在 linux 机器上,两者commsort来自 2012 年 1 月的 GNU coreutils 8.4,并且调用运行良好。

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

4

1 回答 1

1

为了comm工作,它的输入需要排序。它需要与您sort就使用的排序方法达成一致。在 C 语言环境 ( LC_ALL=C) 中,这很容易。字符串一次比较一个字节,第一个不同的字节决定了顺序。

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

运行所有命令LC_ALL=C应该使它们更有可能彼此达成一致。

于 2017-09-15T21:02:59.987 回答