次の形式の大容量ファイルがあります。
2 1019 0 12
2 1019 3 0
2 1021 0 2
2 1021 2 0
2 1022 4 5
2 1030 0 1
2 1030 5 0
2 1031 4 4
値が次の場合2列一致し、次の値を合計したいと思います。3列そして42行の値、それ以外の場合は一意の行の値の合計です。
だから私が望む出力は次のようになります。
2 1019 15
2 1021 4
2 1022 9
2 1030 6
2 1031 8
次の基準に従ってファイルを並べ替えることができます。2列awk
ORを使用しsort
て最後の列の合計を取得しますawk
。ただし、2行ではなく単一行にのみ適用されます。2列マッチ。
答え1
私はPerlでこれをします:
$ perl -lane '$k{"$F[0] $F[1]"}+=$F[2]+$F[3];
END{print "$_ $k{$_}" for keys(%k) }' file
2 1019 15
2 1021 4
2 1030 6
2 1031 8
2 1022 9
またはちょっと:
awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file
2番目の列に基づいて出力を並べ替えるには、次のようにパイプできますsort
。
awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file | sort -k2
どちらのソリューションも最初の列を含みます。アイデアは、最初と2番目の列をハッシュ(perl)または関連配列(awk)のキーとして使用することです。各ソリューションの鍵は、2column1 column2
行目の2列目が同じですが、1列目が異なる場合は別々にグループ化されることです。
$ cat file
2 1019 2 3
2 1019 4 1
3 1019 2 2
$ awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file
3 1019 4
2 1019 10
答え2
おそらくこれが役に立ちます。しかし、列1は常に2であり、結果はそれに応じて変わりますか?
awk '{ map[$2] += $3 + $4; } END { for (i in map) { print "2", i, map[i] | "sort -t't'" } }' file
または述べたようにグレンジャックマンソートの説明:
gawk '{ map[$2] += $3 + $4; } END { PROCINFO["sorted_in"] = "@ind_str_asc"; for (i in map) { print 2, i, map[i] } }' file
答え3
データを事前にソートし、awk に詳細を処理させることができます。
sort -n infile | awk 'NR>1 && p!=$2 {print p,s} {s+=$3+$4} {p=$2}'
積算計をリセットする必要があります。
sort -n infile | awk 'NR>1 && p!=$2 {print p,s;s=0} {s+=$3+$4} {p=$2}'
出力:
1019 15
1021 19
1022 28
1030 34
最初の列を維持するには:
sort -n infile | awk 'NR>1 && p!=$1FS$2 {print p,s} {s+=$3+$4} {p=$1FS$2}'
出力:
2 1019 15
2 1021 19
2 1022 28
2 1030 34
説明する
このp
変数は$2
前の行の値($1FS$2
上記の2番目の場合)を保持します。つまり、現在の行が現在の行と異なる場合()が実行されます{print p,s}
。$2
p!=$2
答え4
Swiss Army Knifeユーティリティの使用mlr
:
mlr --nidx put '$5=$3+$4' then stats1 -g 1,2 -f 5 -a sum infile
出力:
2 1019 15
2 1021 4
2 1022 9
2 1030 6
2 1031 8
メモ:
--nidx
mlr
数値フィールド名を使用するように指示します。put '$5=$3+$4'
新規5番目の場所フィールド、フィールドの合計サムそして4。関数
stats1
(または「動詞
")は、より大きなSwiss Army Knivesのうちより小さいSwiss Army Knifeであり、、、、、、mlr
など様々なアキュムレータベースの機能を備えています。sum
count
mean
など。stats1 -g 1,2
列別にデータをグループ化1そして2-f 5 -a sum
をクリックして、そのグループのフィールドを追加します。5。stats1
名前付きフィールドのみを印刷します。