用于使用公共字段连接两个文件的awk错误代码

时间:2014-06-30 13:54:03

标签: bash awk logic

我想根据第一列中的信息组合两个文件。

$ cat file1

gnl_1045_ 2 -0.74
gnl_1045_ 2 -0.74
gnl_1046_ 10 0.996904   
gnl_1046_ 10 6.904


$ cat file2

gnl_100_ 2 0.42
gnl_100_ 2 0.42
gnl_1025_ 2 0.825
gnl_1025_ 2 0.825
gnl_1046_ 7 4.598512
gnl_1046_ 7 0.4598512

预期输出

gnl_1046_ 10 0.996904   gnl_1046_ 7 4.598512    
gnl_1046_ 10 6.904   gnl_1046_ 7 0.4598512

考虑到我之前的问题(join 2 files based on fields in a columns),我对'awk'代码非常肯定:

awk -F "\t" 'NR==FNR{a[$1]=$0; next}$1 in a{print a[$1],$0}' file1 file2

但它无法正常工作,因为它正确打印'file2'但是'file1'它始终只打印公共字段的第一行:

gnl_1046_ 10 0.996904   gnl_1046_ 7 4.598512    
gnl_1046_ 10 0.996904   gnl_1046_ 7 0.4598512

我真的不明白我的错误在哪里。 有什么建议吗? 谢谢!

2 个答案:

答案 0 :(得分:3)

由于您的1美元不是唯一的,您需要计算每个的出现次数:

$ awk 'NR==FNR{a[$1,++f1[$1]]=$0; next} ($1,++f2[$1]) in a{print a[$1,f2[$1]],$0}' file1 file2
gnl_1046_ 10 0.996904 gnl_1046_ 7 4.598512
gnl_1046_ 10 6.904 gnl_1046_ 7 0.4598512

根据需要将FS和/或OFS更改为标签。

答案 1 :(得分:0)

这里是我的解决方案:

 awk 'NR==FNR{i[$1,FNR]=$0;d[$1];n=FNR;next}
      $1 in d{for(x=1;x<=n;x++)if(i[$1,x]){
           print i[$1,x], $0;delete i[$1,x];break}
       }' file1 file2

好吧我没有把<tab>放在输入文件中,所以你可以稍微调整一下,空格为sep,输出上面的行:

gnl_1046_ 10 0.996904    gnl_1046_ 7 4.598512
gnl_1046_ 10 6.904 gnl_1046_ 7 0.4598512

诀窍是我维护了一个二维数组i(x,y),以便在file1中保存相同$ 1的行,并在一个匹配后,删除带有i(x, min(y))的元素

使用gawk 4测试代码。