我有这样的文件1:
CHR SNP TEST A1 A2 GENO O(HET) E(HET) P
0 AFFX-SNP-000541 ALL 0 0 0/0/0 nan nan 1
0 AFFX-SNP-000541 AFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-000541 UNAFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-002255 ALL 0 0 0/0/0 nan nan 1
0 AFFX-SNP-002255 AFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-002255 UNAFF 0 0 0/0/0 nan nan NA
1 rs12103 ALL C T 55/250/317 0.4019 0.4113 0.5596
1 rs12103 AFF C T 0/0/0 nan nan NA
1 rs12103 UNAFF C T 0/0/0 nan nan NA
1 rs12103_1247494 ALL C T 55/250/321 0.3994 0.4097 0.5581
1 rs12103_1247494 AFF C T 0/0/0 nan nan NA
1 rs12103_1247494 UNAFF C T 0/0/0 nan nan NA
和file2一样:
CHR SNP A1 A2 MAF NCHROBS
0 AFFX-SNP-000541 0 0 NA 0
0 AFFX-SNP-002255 0 0 NA 0
1 rs12103 C T 0.2894 1244
1 rs12103_1247494 C T 0.2875 1252
我想基于SNP名称和TEST == ALL将file2与file1合并,并将CHR,SNP,P和MAF保留在输出file3中。有人知道在终端(Unix)Shell中实现此目标的最佳方法吗?
期望的输出将是:
CHR SNP MAF P
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.2894 0.5596
1 rs12103_1247494 0.2875 0.5581
在这个答案的帮助下
awk 'FNR==NR && FNR>1 {a[$2] = $5; next}
FNR > 1 && ($2 in a) && $3 == "ALL" {
print $1 " " $2 " " a[$2] " " $9
}' file2 file1
要获得标题,只需将其添加到脚本的开头:
BEGIN{print "CHR SNP MAF P"}
解释:
首先,将两个文件传递给awk时,将一个接一个地处理它们。这里有两个重要的变量:NR
是awk
命令开头FNR
的行号,以及是当前文件开头的行号。也就是说,当第一文件进行处理(这里file2的),NR
并且FNR
具有相同的值,这是该行的当前处理的值。但是当awk传递到第二个文件时,FNR
被重置为1,因此NR
与FNR
不再相同。因此,该测试FNR==NR
是了解所处理文件是否为第一个文件的技巧。
因此,让我们看一下代码。条件FNR==NR && FNR>1
测试我们是否正在处理第一个文件而不是第一行。如果是这样,我们将第五列(MAF
)的值存储在由第二个(SNP
)索引的数组中,然后该next
语句说传递给下一行。
当awk处理第二个文件(即file1)时,第一个测试为false,因此awk尝试第二个测试:FNR > 1 && ($2 in a) && $3 == "ALL"
,即:文件的第一行+表中的第二列值(SNP
)不存在a
+表中的第三列值(TEST
)是"ALL"
。如果是这种情况,则将打印列1(CHR
)和两(SNP
),使用来MAF
从数组中获取值a[$2]
,然后打印列九(P
)。
BEGIN{...}
在开头添加一条语句会添加一条仅在处理第一行之前运行的命令。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句