对称差管?

对称差管?

我有一个命令生成一个字符串列表,后跟换行符,,a以及一个包含字符串列表,后跟换行符,的文件b.txt。我需要一个命令来计算 的输出a和内容的对称差b.txt。理想情况下,该命令应在管道中运行,因为a可能非常慢。

如果您喜欢维恩图(维基百科):

对称差分运算

对于那些更注重示例的人:

a输出

apple
car

b.txt

banana
car
dog

那么结果应该是

apple
banana
dog

答案1

您可以使用流程替代将命令的输出视为文件。

comm -3 <(a | sort) <(sort b.txt)

答案2

comm如果您单独对文件进行排序,然后用于查找非公共行,您的排序解决方案可能会更快一些:

sort a.txt -o a.txt
sort b.txt -o b.txt
comm -3 a.txt b.txt | sed 's/^\t//'

或者,如果其中一个数据文件不太大,您可以将其全部读入关联数组,然后逐行比较另一个文件。例如,使用 awk:

awk '
ARGIND==1 { item[$0] = 1; next }
ARGIND==2 { if(!item[$0])print; else item[$0] = 2 }
END   { for(i in item)if(item[i]==1)print i }
' a.txt b.txt

上面ARGIND计算了文件参数。第一行将文件 1 行保存在 array 中item。下一行查看文件 2 中的当前行是否在此数组中。如果没有,则会打印出来,否则我们会注意到该项目在两个文件中都出现过。最后,我们打印两个文件中都没有看到的项目。

如果其中一个文件比另一个文件小得多,最好将其放在 args 的第一位,以便项目数组保持较小:

if [ $(wc -l <a.txt) -lt $(wc -l <b.txt) ]
then args="a.txt b.txt"
else args="b.txt a.txt"
fi
awk '
ARGIND==1 { item[$0] = 1; next }
ARGIND==2 { if(!item[$0])print; else item[$0] = 2 }
END   { for(i in item)if(item[i]==1)print i }
' $args

答案3

一个查看差异的好工具是diff,您只需要稍微使用它的重要选项即可正确格式化输出:

diff --unchanged-group-format= --new-group-format="%>" a b.txt

如果a不是管道文件,那么您应该使用-

echo 'apple
car' | diff --unchanged-group-format= --new-group-format='%>' - b.txt

输出:

apple
banana
dog

或者,如果您不关心文件中出现一行的上下文:

echo 'apple
car' | sort | diff --unchanged-group-format= --new-group-format='%>' - <(sort b.txt)

相关内容