在awk中合并具有共同列的两个文件并打印所有列

3

我有两个非常长的由空格分隔的文件,看起来像这样:

文件1:

CHR SNP   A1 A2 MAF
1    rs12  A G  0.43
1    rs1   A T  0.22
1    1:30  G A  0.012
1    rs23  G A  0.012

文件2:

SNP    CHR A1 A2 MAF CHR:BP
rs21   1   G  A  0.03 1:30
rs13   1   T  A  0.06 1:122
rs23   1   A  G  0.02 1:234

我希望将它们合并在一起,当文件1的第2列与文件2的第1列或文件2的第6列匹配时,打印两个文件的所有列。因此,对于示例,我的输出应该是: file 3。
SNP  CHR A1 A2 MAF CHR:BP CHR SNP  A1 A2 MAF
rs21 1   G  A  0.03 1:30   1  1:30 G  A  0.012
rs23 1   A  G  0.02 1:234  1  rs23 G  A  0.012

我使用了以下代码:
awk 'NR==FNR{a[$2]=$0;next} ($1 in a || $6 in a){print $0 FS a[$2]}' file1 file2 > file3

但不知何故,它过滤掉了正确的行,但只打印file2的列而非file1的列。我也尝试使用join,但即使文件已经排序,它也会给出奇怪的结果。所谓奇怪是指,它大约省略了1/5实际存在于两个文件中的行。但为了完整性,这是我尝试使用join的代码:
join -1 2 -2 1 -o '2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 2.12 2.13 2.14 2.15 1.1 1.2 1.3 1.4 1.5 1.6' <(sort -k2 file1) <(sort -k1 file2) > file3.1

join -1 2 -2 6 -o '2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 2.12 2.13 2.14 2.15 1.1 1.2 1.3 1.4 1.5 1.6' <(sort -k2 file1) <(sort -k6 file2) > file3.2

cat file3.1 file 3.2 > file3

有人看到我的错误了吗?非常感激。 谢谢!


想一想 - 你正在检查 a[$1] 或 a[$6] 是否存在,但是却打印了 a[$2]。 - Ed Morton
我想我对我的语句逻辑完全理解错误了。 我的想法是:我在数组a中保存文件1的$2,每个条目我都保存整行(a[$2]=$0)。 然后我检查文件2的$1或$6是否存在于数组a中。 如果是,则打印文件2的整行($0)以及数组a中每个匹配条目的整行。 - Aron
当您读取file1时,当前行的$2具有某些值,例如rs21,然后当您读取file2时,file2中行的$1或$6具有值rs21,而不是file2中行的$2,该行具有完全不同的值,例如1。当您编写测试代码$1 in a || $6 in a时,显然已经知道了这一点,并且在想要打印a[rs21]时也没有改变。 - Ed Morton
1
如果文件2中的$1和$6都作为文件1中的$2出现在不同的行中,输出应该是什么? - Ed Morton
2个回答

3
您的错误出现在print命令中:
{print $0 FS a[$2]}

应该是

{print $0, ( $1 in a ? a[$1] : a[$6] )}

因为(1)“interesting”字段仅在您处于file1时才在$2中,而不是在遍历file2时,在(2)您需要根据任一条件从数组中提取数据。我们可以使用经典的三元运算符选择哪个数组元素。(我添加了额外的间距以便阅读。)
请注意使用逗号将字段按OFS分隔,而不使用输入字段分隔符FS。
否则,您的代码对我来说看起来很好。

2

请尝试以下操作。

awk 'FNR==NR{a[$2]=$0;next} ($1 in a) || ($6 in a){print $0,a[$1]?a[$1]:a[$6]}'  Input_file1  Input_file2

在这里添加一种非一行解决方案。

awk '
FNR==NR{
  a[$2]=$0
  next
}
($1 in a) || ($6 in a){
  print $0,a[$1]?a[$1]:a[$6]
}'  Input_file1   Input_file2

> file3添加到上述命令中,将输出保存到file3中。 编辑:现在也为OP的代码添加解决方案。
awk 'NR==FNR{a[$2]=$0;next} ($1 in a || $6 in a){print $0 FS a[$1]?a[$1]:a[$6]}' file1 file2 > file3

非常感谢您的超级快速和有用的回答。它有效了!您能解释一下为什么我的awk解决方案不起作用吗?我仍然看不到错误。 而您的解决方案实际上是在检查什么-我不太理解语法。 - Aron
@Aron,请现在也检查我的编辑。 - RavinderSingh13
@Aron,看起来我的提供的代码本身就是你的代码的解决方案 :) - RavinderSingh13
我的意思是,你的打印命令起了作用。 为什么在你的编辑中将a[$1]更改为a[$2]进行打印?(第一个似乎是正确的?) - Aron
@Aron,我只是在尝试解决你的a[$2]a[$6]问题,你可以将其更改为实际的$1,现在让我来做。 - RavinderSingh13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接