我有一个命令生成一个字符串列表,后跟换行符,,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)