2つのファイルがあります。最初のファイルは、2番目のファイルに関心のある行を示すログファイルです(FILTER_FILEと呼びます)。ファイルに重複した行が含まれる可能性があるため、最初のファイルの各固有行に対して2番目のファイルを処理するだけです。
2番目のファイル(DATA_FILEと呼ばれる)には、ファイル1の各行に複数の行が含まれており、最初のファイルで一致する最初の3つの項目について合計する必要がある数字があります(他のファイルは無視できます) )。
私はいくつか試してみましたが、知識はawk
基本にすぎません。できるだけ使い、習得しようとしています。
私がやったやや不器用な試みは次のとおりです。
awk '{print $1 " " $2}' filter_file | sort -u >> tst
while read filter;
do grep "$filter" data_file | head -3; done < tst >> ./short_data_file
while read line;
do grep "$filter" short_data_file | awk '{ sum += $3 } END { print $1 " " $2 " " sum }' ; done < tst >> summary_file
フィルタファイルの例形式:
abcd 123456
abcd 123456
abcd 123456
abcd 123457
abcd 234567
abcd 234567
abcd 234567
abcd 890123
abcd 890123
abcd 890123
abcd 890123
abcd 890123
abde 344566
abde 344566
abde 344566
データファイルのサンプル形式:
abcd 123456 3
abcd 123456 4
abcd 123456 3
abcd 123456 56
abcd 123456 6
abcd 123456 1
abcd 123457 6
abcd 123457 4
abcd 123457 89
abcd 123457 3
abcd 123457 9
abcd 234567 5
abcd 234567 3
abcd 234567 8
abcd 234567 6
abcd 234567 76
abcd 234567 34
abcd 234567 0
abcd 234567 7
abcd 890123 5
abde 344566 152
編集:上記のデータファイルから生成された出力です。
abcd 123456 10
abcd 123457 99
abcd 234567 16
abcd 890123 5
abde 344566 152
編集:実際の実際のデータファイルは、フィルタファイルの場合は数千、データの場合は数百万に達します。
ベストアンサー1
努力する
awk 'NR == FNR { data[$1 " " $2]=0 ; next ; }
{ if ($1 " " $2 in data) data[$1 " " $2]+=$3 }
END { for ( d in data ) printf "%s %d\n",d,data[d] ;} ' filter data
(一行で可能です)
どこ
NR == FNR { data[$1 " " $2]=0 ; next ; }
フィルタファイルに行を保存する{ if ($1 " " $2 in data) data[$1 " " $2]+=$3 }
データに 3 番目の列の値を追加する場合END { for ( d in data ) printf "%s %d\n",d,data[d] ;}
合計を印刷する
出力順序はランダムなので、パイプを介してsort
。
最初の3行
これは修正されたawkです。
NR == FNR { countit[$1 " " $2]=0 ; next ; }
{ if ($1 " " $2 in countit) {
data[$1 " " $2]+=$3 ;
countit[$1 " " $2] ++ ;
if ( countit[$1 " " $2] == 3 ) {
printf "%s %s %s\n",$1,$2,data[$1 " " $2] ;
delete data[$1 " " $2] ;
delete countit[$1 " " $2] ;
}
}
}
END { for ( d in data ) printf "%s %d\n",d,data[d] ;}
不完全なリスト(1つまたは2つの要素など)を処理する方法によっては、END行を削除できます。