bash - awk:如何从文件 A 中提取文件 B 中指定索引的列?

标签 bash unix awk

我的文件A具有以下格式,有数十万列和数千行:

1000->100001    DOSE    2.000   2.000   2.000   2.000   2.000 ....
1001->100101    DOSE    1.988   1.988   2.000   2.000   2.000 ....
1001->100101    DOSE    1.933   2.000   2.000   2.000   2.000 ....
1002->100201    DOSE    2.000   2.000   2.000   2.000   2.000 ....
1002->100201    DOSE    2.000   2.000   2.000   2.000   2.000 ....

虽然我的文件 B(数千个条目)具有以下格式:

SNP,Al1,Al2,Freq1,MAF,AvgCall,Rsq,Genotyped,key,pos,gene_key
20:29649365,C,T,0.93021,0.06979,0.93021,0.10115,,803428,29649365,12
20:29649737,A,G,0.93914,0.06086,0.93914,0.14303,,803442,29649737,12
20:29649765,T,G,0.99963,0.00037,0.99963,0.13918,,803443,29649765,12
20:29650462,A,T,0.89387,0.10613,0.89388,0.12864,,803456,29650462,12

我想做的是从文件 A 中提取前两列以及文件 B 中“关键”列中指定的列。我花了一些时间试图弄清楚如何使用 awk 来完成这项工作,但它一直在对于理论上不应该太难的事情来说太长了。

我的具体问题是:从文件 B 中提取“关键”条目后,如何将这些值通过管道传输到文件 A 的 awk 命令中?

文件 B 中前 3 列的手动命令:

awk '{print $1, $2, $803428, $803442, $803442}' fileA > output.txt 

编辑:

文件 A文件 B 之间没有公共(public)列。 文件 A 中第 803428 列中的值代表来自文件 B 的 SNP“20:29649365”的结果。

如果要运行的命令是:

awk '{print $1, $2, $3, $4, $5}' fileA

结果是:

1000->100001 DOSE 2.000 2.000 2.000 2.000 2.000
1001->100101 DOSE 1.988 1.988 2.000 2.000 2.000
1002->100201 DOSE 1.933 1.999 2.000 2.000 2.000
1003->100301 DOSE 2.000 2.000 2.000 2.000 2.000
1004->100401 DOSE 2.000 2.000 2.000 2.000 2.000

我用来测试作为解决方案给出的 awk 命令的具体示例。

文件A:

1000->100001    DOSE    2.000   2.000   2.000   2.000   2.000
1001->100101    DOSE    1.988   1.988   2.000   2.000   2.000
1001->100101    DOSE    1.933   2.000   1.500   2.000   2.000
1002->100201    DOSE    2.000   2.000   2.000   2.000   1.622
1002->100201    DOSE    2.000   2.000   2.000   2.000   2.000

文件B:

SNP,Al1,Al2,Freq1,MAF,AvgCall,Rsq,Genotyped,key,pos,gene_key
20:29649365,C,T,0.93021,0.06979,0.93021,0.10115,,3,29649365,12
20:29649737,A,G,0.93914,0.06086,0.93914,0.14303,,4,29649737,12
20:29650462,A,T,0.89387,0.10613,0.89388,0.12864,,6,29650462,12

所需的输出(第 1、2、3、4、6 列 - fileB 关键列的最后 3 列):

1000->100001    DOSE    2.000   2.000   2.000
1001->100101    DOSE    1.988   1.988   2.000
1001->100101    DOSE    1.933   2.000   2.000
1002->100201    DOSE    2.000   2.000   2.000
1002->100201    DOSE    2.000   2.000   2.000

最佳答案

好的,这是一个更新版本,应该可以重现您的输出。

awk 'ARGIND==2&&!/SNP/{cols[++i]=$9}ARGIND==4{printf("%s %s",$1,$2);
      for(j=1;j<=i;j++)printf(" %s%s",$cols[j],j<i?"":"\n");}' FS=',' B.txt FS='[ \t]+' A.txt 

由于两个文件中的不同字段分隔符和必须忽略的 B 文件中的标题,这有点复杂。但这里的关键是 $ 接受一个变量,而不仅仅是一个常量整数。此方法将列列表存储在 cols 数组中,并针对 A 中的每一行遍历它们。

文件之间的切换字段分隔符是通过虚拟文件 FS=',' 和 'FS='[\t]+'` 完成的,这意味着我们的实际文件的参数为 2 和 4 .

关于bash - awk:如何从文件 A 中提取文件 B 中指定索引的列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27555009/

相关文章:

linux - 在 bash 命令中输入带格式的字符串

linux - 需要 TAR shell 脚本帮助

bash - 如何在 bash 脚本中的单个命令之后硬编码多个提示问题的答案?

regex - 如何在 awk 中使用 gsub 查找和替换文件中的 ("./") 和 (".txt") 字符

linux - awk 将输出解析为文件,optirun 不起作用

linux - Nmap grep 和 awking 结果

Bash "for"循环,如果条件计数为零?

unix - 在unix/linux中将远程变量的值赋给本地变量

bash - 带有/空格+ ssh的变量

linux - 如何通过时区更改 Linux 中分隔文件中字段的时间戳?