フィールドの一致に基づいて2つのファイルの特定の列をマージします。

フィールドの一致に基づいて2つのファイルの特定の列をマージします。

私がこの質問をした最初の人ではありませんが、私のコードはまだ機能しません。

ファイル1:

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 +

"Parent=tRNA-Tyr6.r01";ファイル1()の$ 10列とファイル2()の$ 1列に基づいてこれら2つのファイルをマージして、"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ユーティリティは、共通の列に基づいて2つのファイルの行をマージします。その列に基づいてファイルを並べ替える必要があります。

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 が 2 番目のファイルのフィールド 1 と一致する場合の行接続を表します。
  • -o …出力するフィールドを一覧表示します。
  • <(sort …)コマンドの出力をsort入力の1つとして使用しますjoin

$'…'そして<(…)純粋なshでは動作しないkshまたはbashが必要です。

すでにソートされている場合はfile2これを使用でき、通常のshで動作します。

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

ファイルの1つの順序を維持したい場合でも使用できますが、最初に行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-

関連情報