awk/joinを使用して列に基づいて項目を結合する

awk/joinを使用して列に基づいて項目を結合する

パイプで区切られた2つのファイルがあり、列1 +列2が両方のファイルで一致する可能性があります。あるいは、あるファイルには項目が含まれ、別のファイルには項目が含まれていない可能性があります。 $1"-"$2 と同じ一致キーを FS として取得するために '|'パイプを使用すると仮定します。

ファイル1

1111|AAA|foo|50
1111|BBB|foo|30
2222|BBB|foo|10

ファイル2

1111|AAA|bar|10
1111|CCC|bar|20
3333|AAA|bar|40

最初の項目に必要な出力は次のとおりです(これがあります)。

1111|AAA|50|10

2番目の項目file1の場合(両方のファイルに一致するcolumn1 + column2がない場合は、fooの欠落項目を0に置き換えます。逆も同様です)

1111|BBB|30|0

ファイル 2 にはあるがファイル 1 にはない項目キー (列 1 + 列 2) の場合 (これは、ファイル 2 の項目 3 に対する期待される出力です。)

3333|AAA|0|40

したがって、目的の出力の完全な形式は、両方のファイルでcolumn1 + column2として表示されるすべての一意のキーを一覧表示することです。 3番目の列項目はファイル1の列4の値(ファイル1に値がない場合は0)、出力の4番目の列はファイル2の列4の値(値がファイル1にない場合)です。ファイル2値の場合は0))です。

研究もたくさん試していろいろ試してみましたが、次のコマンドを使ってみると、file2にはcolumn1+column2ペアがあり、file1にないと私の値は出力されません。

join -t"|" -e0 -a1 -a2 -o 1.2,1.3,1.5,2.5 <(<file1 awk -F"|" '{print $1"-"$2"|"$0}' | sort -k1,1) <(<file2 awk -F"|" '{print $1"-"$2"|"$0}' | sort -k1,1)

file1にはcolumn1 + column2の一致がありますが、file2にはない場合、上記の場合は予想される出力を提供し、存在しない一致に0を追加します...すべてのシナリオで動作させるにはどうすればよいですか?

上記のコマンドは、2つのファイルの列1(column1 + column2)にキーを追加し、新しいキーに基づいて結合していくつかの手続き型置換を実行します。 -e0 キーが file1 にあるが file2 にない場合は 0 が追加されます。新しいキー(column1-column2)がファイル2にはあるがファイル1にはない場合を処理するにはどうすればよいですか?

ベストアンサー1

あなたの方法を使用すると、join2回(またはjoin1回の呼び出しで方法を変更してください。):

  • 共通ラインとペアリングできないfile1ライン印刷join -t'|' -e0 -a1 -o 1.2,1.3,1.5,2.5 <(<file1 awk -F'|' '{print $1"-"$2"|"$0}' | sort -t'|' -k1,1) <(<file2 awk -F'|' '{print $1"-"$2"|"$0}' | sort -t'|' -k1,1)
  • file2ペアリングできないライン印刷join -t'|' -e0 -v2 -o 2.2,2.3,1.5,2.5 <(<file1 awk -F'|' '{print $1"-"$2"|"$0}' | sort -t'|' -k1,1) <(<file2 awk -F'|' '{print $1"-"$2"|"$0}' | sort -t'|' -k1,1)

awk単一の呼び出しで同じ操作を実行できます。$4たとえば、 で索引付けされた 2 つの配列に保存して$1|$2から、ENDブロック内の各配列索引を繰り返し比較し、それに応じて印刷できます。

awk -F'|' 'NR==FNR{z[$1"|"$2]=$4;next}{x[$1"|"$2]=$4}
END{for (j in x){if (!(j in z)){print j, "0", x[j]}};
for (i in z){if (i in x){print i, z[i], x[i]} else {print i, z[i], "0"}}
}' OFS="|"  file1 file2

おすすめ記事