注意,仅能处理第一列没有重复数据的情况。
场景
假设有如下两个文件,两列之间按空格分割:
file.base.txt
1 | aaa 1 |
file.test.txt
1 | ddd 6 |
需要按照第一列取这两个文件的交集,生成新的两份文件,目标结果如下:
file.parsed.base.txt
1 | aaa 1 |
file.parsed.test.txt
1 | aaa 9 |
主要的应用场景是,在测试时,比较基线和策略系统产出数据的 diff。
awk 命令样例
最易懂的方式是写一个 python 脚本,读取两个文件,把第一份文件的内容存内存 map 中,key 为第一列的值,value 为行,然后用第二份文件的第一列去匹配 map 。这个执行逻辑通过 awk 命令也可以实现,指令如下
1 | awk 'NR==FNR{a[$1]=$0;next}NR>FNR{if($1 in a)print $0"\n"a[$1]}' file.test.txt file.base.txt > file.tmp |
对于第一个 awk 表达式中的命令,解释如下(版权归属 gpt):
NR==FNR{a[$1]=$0;next}
:在处理第一个文件(file.test.txt)时,NR
(当前处理的总行数)和FNR
(当前文件的行数)是相等的。这个表达式的作用是创建一个数组a
,索引是每行的第一列的值$1
,值是整行内容$0
。next
命令则使awk跳过后面的处理,直接开始处理下一行。NR>FNR{if($1 in a)print $0"\n"a[$1]}
:当处理第二个(file.base.txt)和后续文件时,NR
将大于FNR
。这个表达式的作用是检查当前行的第一列的值$1
是否在数组a
的索引中。如果在,就打印当前行$0
,然后打印一个换行符\n
,接着打印数组a
中与$1
对应的值a[$1]
(即第一个文件中相应行的内容)。
此时 file.tmp 中偶数行存的是过滤后的 test 数据,奇数行存的是过滤后的 base 数据,后面两个命令就是将这两个部分数据提取出来,然后再按照第一列排个序。
如果有重复数据
假如两份原始文件中第一列存在重复的数据,那么执行就会有问题。根据之前的分析,file.test.txt 中的第一列会作为 key 存到 a
中,那么如果有重复数据,a
中存的就是重复数据最后一个的值,也即最终的结果里,file.test.txt 的数据会有问题,样例如下
file.base.txt
1 | aaa 1 |
file.test.txt
1 | aaa 7 |
处理的结果为:
file.parsed.base.txt
1 | aaa 1 |
file.parsed.test.txt
1 | aaa 11 |
暂时还没想到好的办法处理