我有一个关于根据不按顺序的相应列比较两个文件的问题。
文件1
AAAA,BBBB,CCCC,DDDD,EEEE,FFFF,GGGG,HHHH (header)
a,b,c,d,e,f,g,h
aa,bb,cc,dd,ee,ff,gg,hh
aaa,bbb,ccc,ddd,eee,fff,ggg,hhh
文件2
GGGG,AAAA,CCCC,DDDD,HHHH,EEEE,BBBB,FFFF,IIII (header)
g,a,c,d,h,e,b,f,i
gg,aa,cc,dd,hh,ee,bb,ff,ii
在上面的示例中,我必须将文件 1 中的 4 个不同列与文件 2 中的 4 列进行比较,如果找到匹配项,请使用添加的列更新文件 2 并表示已匹配,并且不要再次使用该行进行比较并替换上的列文件 1 中包含文件 2 中的列
比较文件 1 和文件 2 中从 a 到 h 的 6 列,如果找到匹配,则将 a 列替换为 i 列
最终文件应该是文件3
AAAA,BBBB,CCCC,DDDD,EEEE,FFFF,GGGG,HHHH
i,b,c,d,e,f,g,h
ii,bb,cc,dd,ee,ff,gg,hh
答案1
使用磨坊主( mlr
) 对两个文件共有的命名字段执行关系 JOIN 操作:
$ mlr --csv join -j AAAA,BBBB,CCCC,DDDD,EEEE,FFFF,GGGG,HHHH -f file1.csv file2.csv
AAAA,BBBB,CCCC,DDDD,EEEE,FFFF,GGGG,HHHH,IIII
a,b,c,d,e,f,g,h,i
aa,bb,cc,dd,ee,ff,gg,hh,ii
AAAA
然后,为了用 的内容替换该列的内容,IIII
我们可以将该IIII
列移动到开头,同时删除该AAAA
列(这是通过 Millercut
操作完成的),然后重新标记IIII
为AAAA
(这是通过 Millerlabel
操作完成的):
mlr --csv \
join -j AAAA,BBBB,CCCC,DDDD,EEEE,FFFF,GGGG,HHHH -f file1.csv then \
cut -o -f IIII,BBBB,CCCC,DDDD,EEEE,FFFF,GGGG,HHHH then \
label AAAA file2.csv
该cut
操作可以分为两个单独的步骤;一个排除该AAAA
字段,另一个对剩余字段重新排序,使其IIII
成为第一个字段。这将使我们能够避免长长的字段列表:
mlr --csv \
join -j AAAA,BBBB,CCCC,DDDD,EEEE,FFFF,GGGG,HHHH -f file1.csv then \
cut -x -f AAAA then \
reorder -f IIII then \
label AAAA file2.csv
最终输出:
AAAA,BBBB,CCCC,DDDD,EEEE,FFFF,GGGG,HHHH
i,b,c,d,e,f,g,h
ii,bb,cc,dd,ee,ff,gg,hh