1つのフィールドに2つのファイルを結合する

1つのフィールドに2つのファイルを結合する

両方のファイルを比較し、比較結果に応じて最初のファイルに新しい列を追加する必要があります。 C 列は主キーです。

A,B,C,D
1,1990,I001,2473264
2,1991,I002,2473265
3,1992,I004,2473266
4,1993,6050,912432
5,1994,6003,912433

2番目のファイル

A,B
I001,2.3 GHz
I002,2.3 GHz
I004,2.3 GHz
6050,1.8 GHz
6003,850 MHz

期待される出力

A,B,C,D,E
1,1990,2.3 GHz,I001,2473264
2,1991,2.3 GHz,I002,2473265
3,1992,2.3 GHz,I004,2473266
4,1993,1.8 GHz,6050,912432
5,1994,850 MHz,6003,912433

このコードは正常に動作しますが、レコードが一致しない場合は、最初のファイルの行をスキップします。しかし、スキップしてその列にゼロまたはNAを追加したくありません。

awk -F, 'NR==FNR{a[$1]=$2;next}a[$3]{print $0","a[$3]}' test2 test1
A,B,C,D
1,1990,I001,2473264
2,1991,I002,2473265
3,1992,I004,2473266
4,1993,6050,912432
5,1994,6003,912433
6,1995,6004,21234

予想出力:

1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0

答え1

awk次に変更してください。

$ awk -F, 'NR==FNR{a[$1]=$2;next} FNR!=1{print $0","(a[$3]?a[$3]:"NA")}' SECOND FIRST
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
6,1995,6004,21234,NA

初めて目的の結果を得るには:

$ awk -F, 'NR==FNR{a[$1]=$2;next} FNR!=1{$3=(a[$3]?a[$3]:"NA")","$3; print}' OFS=, SECOND FIRST
1,1990,2.3 GHz,I001,2473264
2,1991,2.3 GHz,I002,2473265
3,1992,2.3 GHz,I004,2473266
4,1993,1.8 GHz,6050,912432
5,1994,850 MHz,6003,912433
6,1995,NA,6004,21234

答え2

awkあなたのプログラムを次のように修正すると正しいです。無条件使用

print $0","( a[$3] ? a[$3] : 0 )

使用する代わりに

print $0","a[$3]

a[$3]0でないか空の場合。つまり、a[$3]フィールドが0または空の場合は0を使用し、それ以外の場合は使用しますa[$3]

つまり、

awk -F, -v OFS=',' 'FNR==NR { a[$1]=$2; next } FNR > 1 { print $0, (a[$3] ? a[$3] : 0) }' fileB fileA

FNR > 1ここではヘッダーをスキップするために使用します。


使用join:

$ join -t , -1 3 -o 1.1,1.2,1.3,1.4,2.2 fileA fileB
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz

ファイルが結合キーでソートされていない場合(プロセス置換をサポートするシェルで):

$ join -t , -1 3 -o 1.1,1.2,1.3,1.4,2.2 <( sort -t, -k3,3 fileA ) <( sort fileB )
5,1994,6003,912433,850 MHz
4,1993,6050,912432,1.8 GHz
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz

操作は両方のファイルで行われますjoin。カンマがフィールド区切り記号であることをINNER JOIN示すことで-t ,、3番目のフィールドを最初のファイルの結合キーとして選択します(そのファイルで同じ別のフィールドを使用しない限り、2番目のファイルの最初のフィールドがキーであると仮定します)。join-1 3-2 NN

この-oフラグは、join出力に含めるフィールドとファイル(x.yファイルの列を表す)を通知します。yx

joinとても速い仕事ですが、必要入力ファイルは結合キーに基づいてソートされます(上記の最初の例を見ることができる幸運がありました)。上記の第2の例の最終出力は整列していない。最初フィールドですが、パイプを介して簡単に解決できますsort -k1,1n


2番目のケースでは、不一致のため

$ join -t, -1 3 -o1.1,1.2,1.3,1.4,2.2 -a 1 -e 0  <( sort -t, -k3,3 fileA ) <( sort fileB )
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0
4,1993,6050,912432,1.8 GHz
A,B,C,D,0
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz

追加すると、最初のファイルのすべてのフィールドが常に出力され、2番目のファイルの各欠落フィールドにゼロが挿入されるように-a 1 -e 0要求されます。join(-a 1

ご覧のとおり、正しい結果が得られましたが(私たちが要求したので)最初のファイルのヘッダーも含めました。両方のファイルのデータからヘッダーを削除して結果を並べ替えるには、次のようにします。

$ join -t, -1 3 -o1.1,1.2,1.3,1.4,2.2 -e 0 -a1  <( tail -n +2 fileA | sort -t, -k3,3 ) <( tail -n +2 fileB | sort ) | sort -k1,1n
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0

このコマンドは実際に両方の状況に適用されます。

答え3

使用牛に似た一種の栄養 join拡張データと最初echoヘッダーを置き換えるための出力形式tailjoin一貫性のないヘッダーのために混乱する可能性があるため):

echo A,B,C,D,E
join -t ',' --header --nocheck-order test1 test2 \
     -a 1 -e NA -1 3 -2 1 -o 1.1,1.2,2.2,1.3,1.4 | tail -n +2

出力:

A,B,C,D,E
1,1990,2.3 GHz,I001,2473264
2,1991,2.3 GHz,I002,2473265
3,1992,2.3 GHz,I004,2473266
4,1993,1.8 GHz,6050,912432
5,1994,850 MHz,6003,912433
6,1995,NA,6004,21234

関連情報