このように2つのテーブルをマージしたい
1番テーブル
Chr1 5
Chr1 10
Chr1 20
Chr2 10
Chr2 30
表2
Chr1 10 value value2
Chr1 20 value value2
Chr2 30 value value2
希望の出力
Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2
2つのテーブルの2つの列に一致する行のみを保持するテーブルをマージするために、awkでスクリプトを見つけました。ただし、ここではTable_1のすべての行が必要ですが、一致する場合はTable_2の値を追加します。これを達成する方法を教えてもらえますか?
答え1
$ awk '{ key = $1 FS $2 };
NR == FNR { t[key] = $0; next };
key in t { print t[key]; next };
1' table2.txt table1.txt
Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2
読み取った各入力行では、(読み取った両方のファイルに対して)変数は最初の2つのフィールド
key
($1
および$2
)に設定され、その間にはフィールド区切り文字(FS
)があります。FS
両方のフィールドに含まれないことが保証される唯一の文字であるため、一意のキーを生成することが保証される唯一の文字であるために使用されます。キーは、関連配列のインデックスとして使用されますt
。table2.txt
読むとき(〜しなければならないコマンドラインの最初のファイル名引数としてリストされています)、各入力行は配列の1つの要素に格納されますt
。重複した項目が含まれている場合にのみ記憶されます
table2.txt
。つまり、最初の2つのフィールドが同じ複数行を持つ場合です。最後一つは見る。これらのすべての重複項目(表示される順序で)を覚えている場合は、awkスクリプトの2行目を次のように変更してください。NR == FNR { if (key in t) { t[key] = t[key] "\n" $0 } else { t[key] = $0 }; next };
最初のファイルの読み取りが終了したら
table1.txt
(2番目のファイル名arg)を読み取り、配列に対応するエントリがある場合は印刷しtable2
、それ以外の場合は現在の行を印刷します。1
スクリプトの最後の行はawk
awkの慣用的な略語です{print}
。値が1
true と評価され、一部の値が true と評価された場合、デフォルトのアクションは現在の行を印刷することです。
メモ:table2.txt
容量が大きいとRAMが大量に使用されます。これは、ギガバイトのRAMを備えた最新のシステムでは問題にはなりません。
答え2
$ awk '{k=$1 FS $2} NR==FNR{map[k]=$0; next} {print (k in map ? map[k] : $0)}' table2 table1
Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2