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
是怎么回事?当我将 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
combined
和 combined-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-again
到grep
的一些输出行,这些行确实存在。我完全不知道为什么 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:
根据评论中的一些建议进行更多调查后,问题似乎可能是由于 comm
和 sort
工具的版本控制所致。
I 运行 mac 上的所有上述命令,其中 comm
来自 BSD 2005 年 1 月 26 日,sort
来自 GNU coreutils,排序 5.93 2005 年 11 月。
在 linux 框中,comm
和 sort
均来自 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
的命令应该会让它们更容易达成一致。
我有两个文件,每行列出一堆不同的文件名。我合并它们,对它们进行排序,然后检查 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
combined
和 combined-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-again
到grep
的一些输出行,这些行确实存在。我完全不知道为什么 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:
根据评论中的一些建议进行更多调查后,问题似乎可能是由于 comm
和 sort
工具的版本控制所致。
I 运行 mac 上的所有上述命令,其中 comm
来自 BSD 2005 年 1 月 26 日,sort
来自 GNU coreutils,排序 5.93 2005 年 11 月。
在 linux 框中,comm
和 sort
均来自 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
的命令应该会让它们更容易达成一致。