[英]compare columns from different files and print those that DO NOT match
我有两个文件,file1和file2。 我想比较file1的几列-$ 1,$ 2,$ 3和$ 4与file2的几列$ 1,$ 2,$ 3和$ 4,并打印出与file1中的任何行都不匹配的file2行。
例如
文件1
aaa bbb ccc 1 2 3
aaa ccc eee 4 5 6
fff sss sss 7 8 9
文件2
aaa bbb ccc 1 f a
mmm nnn ooo 1 d e
aaa ccc eee 4 a b
ppp qqq rrr 4 e a
sss ttt uuu 7 m n
fff sss sss 7 5 6
我想作为输出:
mmm nnn ooo 1 d e
ppp qqq rrr 4 e a
sss ttt uuu 7 m n
我在这里看到了一些问题,这些问题是寻找匹配的问题并打印出来的,反之则不匹配的问题。
谢谢!
使用以下脚本:
awk '{k=$1 FS $2 FS $3 FS $4} NR==FNR{a[k]; next} !(k in a)' file1 file2
k
是各列的连接的值1
, 2
, 3
和4
,由分隔FS
(见注释 ),以及将被用作在搜索阵列的关键a
后面。 读取file1
NR==FNR
为true
。 我在读取file1
同时创建了a
由k
索引的数组。
对于其余的输入行,我用!(k in a)
检查索引是否在a
中不存在。 如果计算结果为true
awk
将打印该行。
如果文件已排序并且知道使用的字符集,则这是另一种方法。
$ function f(){ sed 's/ /~/g;s/~/ /4g' $1; }; join -v2 <(f file1) <(f file2) |
sed 's/~/ /g'
mmm nnn ooo 1 d e
aaa ccc eee 4 a b
ppp qqq rrr 4 e a
sss ttt uuu 7 m n
fff sss sss 7 5 6
通过串联前四个字段(使用~
字符,但可以使用任何未使用的字符)来创建键字段,使用join
从file2中查找不匹配的条目,然后将合成键字段重新分区。
但是,最好的方法是使用带有轻微修复的awk
解决方案
$ awk 'NR==FNR{a[$1,$2,$3,$4]; next} !(($1,$2,$3,$4) in a)' file1 file2
毫无疑问,@ hek2mgl的awk
解决方案比此解决方案要好,但是对于信息来说,也可以使用uniq
, sort
和rev
:
rev file1 file2 | sort -k3 | uniq -u -f2 | rev
rev
正在将两个文件从右还原到左。
sort -k3
正在跳过第一列的第二行。
uniq -u -f2
仅打印唯一的行(比较时先跳过2)。
最后, rev
恢复到原来的水平。
此解决方案对两个文件的行进行排序。 这可能是希望的,也可能不是。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.