*nix:执行集合列表的并/交/差



我有时需要比较两个文本文件。显然,diff显示了不同之处,也隐藏了相似之处,这就是关键所在。

假设我想对这些文件进行其他比较:集合并、交集和减法,将每一行作为集合中的一个元素。

是否有类似的简单通用实用程序或一行程序可以做到这一点?


例子:

a.txt

john
mary

b.txt

adam
john

$> set_union a.txt b.txt
john
mary
adam

$> set_intersection a.txt b.txt
john

$> set_difference a.txt b.txt
mary

联盟:sort -u 文件…

交集:sort 文件… | uniq -d

整体差异(仅在一个文件中的元素):
sort 文件… | uniq -u

数学差异(元素在一个文件中只出现一次):
sort 文件… | uinq -u | sort - <(sort -u fileX ) | uniq -d

前两个命令获取所有唯一元素。然后我们将它与我们感兴趣的文件合并。sort - <(sort -u fileX ):

-将处理stdin(即所有唯一元素的列表)。

<(...)执行命令,将输出写入临时文件,并将文件的路径传递给命令。

所以这给出了所有唯一元素加上fileX中所有唯一元素的组合。重复项是唯一的元素,只在fileX中。

如果您想获得两个文件之间的公共行,您可以使用comm实用程序。

A.txt:

A
B
C

B.txt

A
B
D

,然后,使用comm将得到:

$ comm <(sort A.txt) <(sort B.txt)
        A
        B
C
    D

在第一列中,您拥有第一个文件中而不是第二个文件中的内容。

在第二列中,您拥有第二个文件中而不是第一个文件中的内容。

第三列是两个文件中的内容

如果您不介意使用一点Perl,并且如果您的文件大小合理,可以将它们写入散列,那么您可以将这些文件收集为两个散列来执行:

#...get common keys in an array...
my @both_things
for (keys %from_1) {
    push @both_things, $_ if exists $from_2{$_};
}
#...put unique things in an array...
my @once_only
for (keys %from_1) {
    push @once_only, $_ unless exists $from_2($_);
}

我不能评论Aaron Digulla的答案,尽管它被接受,但实际上并没有计算集合差。

给定输入的集差AB应该只返回mary,但接受的答案也错误地返回adam

这个答案有一个awk的一行代码,可以正确地计算集合差值:

awk 'FNR==NR {a[$0]++; next} !a[$0]' b.txt a.txt

最新更新