根据字段匹配合并 2 个文件的特定列

根据字段匹配合并 2 个文件的特定列

我知道我不是第一个问这个问题的人,但我的代码仍然无法工作:

文件一:

gi|1283| tRNAscan exon 87020 88058 . - . transcript_id "Parent=tRNA-Tyr5.r01";
gi|3283| tRNAscan exon 97020 97058 . + . transcript_id "Parent=tRNA-Tyr6.r01";
gi|4283| rRNAscan exon 197020 197058 . - . transcript_id "Parent=rRNA-Tyr1.r01";
gi|5283| mRNAscan exon 295020 298059 . + . transcript_id "Parent=mRNA-Tyr2.r01";

该文件是制表符分隔的。

文件2:

"Parent=tRNA-Tyr6.r01"; 12
"Parent=mRNA-Tyr2.r01"; 0

该文件也是制表符分隔的。

期望的输出:

"Parent=tRNA-Tyr6.r01"; 12 -
"Parent=mRNA-Tyr2.r01"; 0 +

我想根据文件 1 中的 $10 列 ( "Parent=tRNA-Tyr6.r01";) 和文件 2 中的 $1 列 ( "Parent=tRNA-Tyr6.r01";) 合并这两个文件,并附加文件 1 中的 $7 列 ( -/ +)

我的解决方案是这样的:

awk 'FNR==NR{a[$10]=$7;next} ($1 in a) {print $1,"2,a[$1]}' file2 file1 > Output

谁能帮我吗?

答案1

join实用程序基于公共列合并两个文件的行。它要求文件在该列上排序。

join -t $'\t' -1 10 -2 1 -o 2.1,2.2,1.7 <(sort -t $'\t' -k10 file1) <(sort -t $'\t' file2)
  • $'\t'是一个制表符,-t $'\t'表示使用它作为字段分隔符。
  • join -1 10 -2 1表示当第一个文件的字段 10 与第二个文件的字段 1 匹配时连接行。
  • -o …列出要输出的字段。
  • <(sort …)使用命令的输出sort作为 的输入之一join

$'…'并且<(…)需要 ksh 或 bash,它们不能在纯 sh 中工作。

如果file2已经排序,那么你可以使用它,它在普通 sh 中工作:

sort -t $'\t' -k10 file1 |
join -t "$(printf \\t)" -1 10 -2 1 -o 2.1,2.2,1.7 - file2

如果您想保留其中一个文件的顺序,您仍然可以使用join,但首先添加行号,最后按原始行号排序。例如,要保留以下顺序file2

join -t $'\t' -1 10 -2 1 -o 2.1,2.2,2.3,1.7 \
     <(sort -t $'\t' -k10 file1) \
     <(<file2 nl | sort -t $'\t' -k 2,2) |
sort | cut -d $'\t' -f 2-

相关内容