両方のファイルを比較し、比較結果に応じて最初のファイルに新しい列を追加する必要があります。 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 N
N
この-o
フラグは、join
出力に含めるフィールドとファイル(x.y
ファイルの列を表す)を通知します。y
x
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
ヘッダーを置き換えるための出力形式tail
(join
一貫性のないヘッダーのために混乱する可能性があるため):
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