8つの列と数百万の行を含むCSVファイル(フィールド区切り文字が実際にはカンマである)があります。例は次のとおりです。
1000024447,38111220,201705,181359,0,12,1,3090
1064458324,38009543,201507,9,0,1,1,1298
1064458324,38009543,201508,9,0,2,1,90017
与えられた列のすべての数字の合計と読み取った行数を印刷する最速の方法は何ですか?何が速くなるかを説明できますか?
答え1
$ datamash -t, count 3 sum 3 < file
3,604720
いくつかのテスト
$ time gawk -F',' '{ sum += $3 } END{ print sum, NR }' longfile
604720000000 3000000
real 0m2.851s
user 0m2.784s
sys 0m0.068s
$ time mawk -F',' '{ sum += $3 } END{ print sum, NR }' longfile
6.0472e+11 3000000
real 0m0.967s
user 0m0.920s
sys 0m0.048s
$ time perl -F, -nle '$sum += $F[2] }{ print "$.,$sum"' longfile
3000000,604720000000
real 0m3.394s
user 0m3.364s
sys 0m0.036s
$ time { cut -d, -f3 <longfile |paste -s -d+ - |bc ; }
604720000000
real 0m1.679s
user 0m1.416s
sys 0m0.248s
$ time datamash -t, count 3 sum 3 < longfile
3000000,604720000000
real 0m0.815s
user 0m0.716s
sys 0m0.036s
したがってmawk
、datamash
と が群れの中で最善の選択であるようです。
答え2
Awk
テキストファイルを処理するための高速で高性能なツールです。
awk -F',' '{ sum += $3 }
END{ printf "Sum of 3rd field: %d. Total number of lines: %d\n", sum, NR }' file
出力例:
Sum of 3rd field: 604720. Total number of lines: 3
コンセプトノート:これらの非選択肢はすべて、「理想的な」数値列に対してのみ高速に実行される
ことに注意してください。awk
少し複雑な形式(たとえば、計算前に削除するための追加情報など<1064458324:a,<38009543:b,<201507:c,<9:d,<0:e,<1:f,<1:g,1298
)がある場合、これらの速度の利点はすべて消えます(処理を必要としないいくつかの利点は言うまでもありません)。
答え3
抽出フィールドを使用して、cut
数字の間にpaste
記号を挿入して合計することができます。これを使用して行数を計算できます。+
bc
wc
しかし、何百万行のパフォーマンスがどうなのかわかりません。しかし、パフォーマンスの黄金率は推測せずに測定することです。すべてのソリューションを分析して、必要なパフォーマンスを提供していることを確認し、変更によってパフォーマンスが向上または低下するかどうかを判断する必要があります。
以下は、与えられたフィールドを合計して行数を印刷するソリューションです。
echo -n "Sum: "
cut -d, -f3 <file |paste -s -d+ |bc
echo -n "Lines: "
wc -l <file
出力:
Sum: 604720
Lines: 3
このフィールドはここで-f#
toパラメータとして指定されます。cut
cut -f3