匹配两个文件中的第 1-5 列,并打印匹配的第 1-5 列以及文件 1 的第 6 和第 7 列以及文件 2 的第 6 列

匹配两个文件中的第 1-5 列,并打印匹配的第 1-5 列以及文件 1 的第 6 和第 7 列以及文件 2 的第 6 列

想要匹配 2 个文件中的第 1-5 列,并打印第 1-5 列以及文件 1 中的第 6 和第 7 列以及文件 2 中的第 6 列。两个文件中的不匹配行也应该在不匹配列中打印 NA 值

file1

12  800000  900000  66  73  0   0  
12  900000  1000000 73  48  2   2  
13  1000000 1100000 11  11  0   0  
12  1100000 1200000 12  12  0   0  
18  1400000 1600000 33  33  3   3  

file2

12  800000  900000  66  73  145(28.12)  
12  900000  1000000 73  48  703(51.17)  
13  1000000 1100000 11  11  545(43.99)  
12  1100000 1200000 12  12  699(45.30)
14  16100000    16200000    0   0   11(14.50)  
14  16200000    16300000    0   0   0    

Expected output

12  800000  900000  66  73  145(28.12)  0  0   
12  900000  1000000 73  48  703(51.17)  2  2  
13  1000000 1100000 11  11  545(43.99)  0  0  
12  1100000 1200000 12  12  699(45.30)  0  0  
14  16100000  16200000  0  0  11(14.50)  NA  NA 
14  16200000  16300000  0  0  0  NA  NA  
18  1400000 1600000 33  33  NA  3   3

我尝试了下面的 awk 命令,但没有从两个文件中获取列

awk 'FNR==NR{A[$1 FS $2 FS $3 FS $4 FS $5]=$3;next}{print ($1 FS $3 FS $4 FS $5 in A ) ? $0 OFS A[$1 FS $3 FS $4 FS $5] : $0 OFS "NA"}' file1 file2

答案1

您的代码与您的描述不匹配,例如,它存储 file1 中的 $3 以便稍后打印,但您说您想打印 $4 和 $6,然后您的预期输出与其中任何一个都不匹配,而是显示 file1 中的 $6 和 $7。因此,根据您的预期输出,我认为这就是您想要的:

$ cat tst.awk
{ key = $1 OFS $2 OFS $3 OFS $4 OFS $5 }
FNR==NR {
    file1[key] = $6 OFS $7
    next
}
{
    print $0, (key in file1 ? file1[key] : "NA" OFS "NA")
    delete file1[key]
}
END {
    for ( key in file1 ) {
        print key, "NA", file1[key]
    }
}

$ awk -f tst.awk file1 file2
12  800000  900000  66  73  145(28.12) 0 0
12  900000  1000000 73  48  703(51.17) 2 2
13  1000000 1100000 11  11  545(43.99) 0 0
12  1100000 1200000 12  12  699(45.30) 0 0
14  16100000    16200000    0   0   11(14.50) NA NA
14  16200000    16300000    0   0   0 NA NA
18 1400000 1600000 33 33 NA 3 3

请注意使用变量来保存两个文件的键索引。当您有一个由值组合而成的键时,不要尝试在代码中多次写入它,因为很容易出错,就像$2在处理 file2 时忘记包含在映射的查找中一样(您使用了$1 FS $3 FS $4 FS $5 in A而不是$1 FS $2 FS $3 FS $4 FS $5 in A并在 ) 中再次做了同样的事情A[$1 FS $3 FS $4 FS $5]

另外 - 不要使用所有大写变量名称(例如A)以避免与内置变量名称发生冲突,并且使用括号使代码更清晰(如果没有其他的话),例如 idk if$1 FS $2 in A意味着(即与查找结果的($1 FS) ($2 in A)串联)或(即查找in串联的结果)或其他东西,但如果你简单地写它,那么它就清晰且明确。$1 FS$2 in A($1 FS $2) in A$1 FS $2A($1 FS $2) in A

最后请注意,我使用OFS而不是FS作为数组索引分隔符 - 这是因为在代码中我们在该END部分中打印该值,并且应该分隔输出字段的是OFS,而不是FS。在这种情况下,它们都是相同的东西,一个空白字符,所以你不会看到差异,但如果你想输出 CSV,那么使用我的代码,你需要做的就是添加,-v OFS=','它会按原样工作,而如果您FS在数组索引下标之间使用,那么您需要更改它。

相关内容