今天遇到一个问题就是两个大文件,其中一个文件是另一个文件的子集,需要找出不同的部分,上网查询后得到如下方法:
方法一:comm命令实现
首先看看comm命令的帮助
comm --help
Usage: comm [OPTION]... FILE1 FILE2
Compare sorted files FILE1 and FILE2 line by line.
-1 suppress column 1 (lines unique to FILE1)
-2 suppress column 2 (lines unique to FILE2)
-3 suppress column 3 (lines that appear in both files)
Examples:
comm -12 file1 file2 Print only lines present in both file1 and file2.
comm -3 file1 file2 Print lines in file1 not in file2, and vice versa.
-1 不显示只在第1个文件里出现过的列。
-2 不显示只在第2个文件里出现过的列。
-3 不显示只在第1和第2个文件里出现过的列。
--help 在线帮助。
--version 显示版本信息。
例子
comm - 12 就只显示在两个文件中都存在的行;
comm - 23 只显示在第一个文件中出现而未在第二个文件中出现的行;
comm - 123 则什么也不显示。
注意:两个文件比较前,一定要进行sort排序。不然输出的结果可能是错的。
方法二:使用diff命令比较
diff命令是一个比较经典的文本比较工具了,diff命令较comm的参数要多。其经常和patch命令组合使用,进行补丁升级。其默认使用的是-a参数,即逐行比较两个文件之间的不同。此处我们要实现想要得到的结果,还需要配合grep和awk实用:
diff 2.txt 1.txt |grep "<"|awk ' $1 = " " '
注意:在使用diff命令时候,也需要预先对文件进行sort排序,不然输出可能出错。
方法三:awk实现
awk应该算是shell常用命令中的泰山北斗了,几乎很多其他命令能完成的工作,awk都能完成(只不过有些写起来可能比较复杂)。本例中也不例外:
awk 'NR==FNR{a[$0]++} NR>FNR&&!a[$0]' 1.txt 2.txt
找出两个文件之间的相同部分可以使用
awk 'NR==FNR{a[$0]++} NR>FNR&&a[$0]' 1.txt 2.txt
下面的两个语句也可以换成:
awk 'NR==FNR{a[$0]}NR>FNR{ if(!($1 in a)) print $0}' file1 file2 找出文件2中不同的值
awk 'NR==FNR{a[$0]}NR>FNR{ if($1 in a) print $0}' file1 file2 找出两文件中相同的值
注:
1、awk实现时,并不需要事先对两个文件进行sort排序,
2、注意和上两个命令中两个文件的放置顺序是不同的。三种实现方法,文件的顺序一定颠倒,颠倒了,效果就刚好想反了,就变成找出文件1中有文件2中没有的行了。
方法四:grep误人子弟法
网上另外流传一个错误的方法,即通过grep命令实现:
grep -v -f 1.txt 2.txt 经测试,无论事先是否对两个文件进行sort倒序,此方法输出的结果,发现都是不正确的。