CSVファイル:各値の最初のパターンに基づいて値をグループ化して合計します。

CSVファイル:各値の最初のパターンに基づいて値をグループ化して合計します。

私はbashを使用してCSVファイル内のフィールドを見つけ、グループ化し、合計するスクリプトを作成しています。各行にはカンマ区切りのフィールドがあり、それぞれ同様の規則に従います。カンマで区切られた各フィールドには、数値、等号(=)、英数字の値が順番に表示されます。 「(数字)=」は1行に表示されない場合があります。その場合、フィールドの位置は異なる場合がありますが、1行に1回のみ表示されます。また、等号の後の値の長さも異なります。

私の目標の例は最高です。 CSVファイル:

35=D,11=ABCD1,1=ABC,55=XYZ,38=100,40=P,18=M,54=1,59=0,10=111
35=D,11=ABCD2,1=ABC,55=XYZ,40=P,18=M,38=200,54=1,44=10.00,59=0,10=133
35=D,11=ABCD3,1=ABC,55=XYZ,40=P,18=M B,54=1,38=300,44=10.00,59=0,110=200,10=113
35=D,11=ABCD4,1=ABC,55=XYZ,38=400,40=P,18=M B F,54=1,44=10.00,59=0,110=300,10=144
35=D,11=ABCD5,1=ABC,55=ZYX,38=300,40=2,54=1,44=10.00,59=3,10=132
35=D,11=ABCD6,1=ABC,55=ZYX,38=100,40=1,18=C,54=2,59=3,10=131

「38 =」で始まるすべてのフィールドを識別し、「=」の後のすべての数値を合計して各「55 =」にグループ化するスクリプトが必要です。各行には「38 =」と「55 =」があります。

上記のファイルを使用した出力は次のとおりです(ソートはオプション)。

55=XYZ 38=1000
55=ZYX 38=400

答え1

ミラーを使ってhttp://johnkerl.org/miller/doc、これからinput.csv

35=D,11=ABCD1,1=ABC,55=XYZ,38=100,40=P,18=M,54=1,59=0,10=111 35=D,11=ABCD2,1=ABC,55=XYZ,40=P,18=M,38=200,54=1,44=10.00,59=0,10=133 35=D,11=ABCD3,1=ABC,55=XYZ,40=P,18=M B,54=1,38=300,44=10.00,59=0,110=200,10=113 35=D,11=ABCD4,1=ABC,55=XYZ,38=400,40=P,18=M B F,54=1,44=10.00,59=0,110=300,10=144 35=D,11=ABCD5,1=ABC,55=ZYX,38=300,40=2,54=1,44=10.00,59=3,10=132 35=D,11=ABCD6,1=ABC,55=ZYX,38=100,40=1,18=C,54=2,59=3,10=131

そして走っている

mlr --ofs " " unsparsify then stats1 -a sum -f 38 -g 55 then rename 38_sum,38 input.csv

あなたはやる

55=XYZ 38=1000 55=ZYX 38=400

答え2

Steeldriverは私に少し勝ったが、私は見つけた。

perl -F'[=,]' -lane '
        %row = @F;
        $sum{$row{55}} += $row{38};
    }{ 
        print "$_ = $sum{$_}" for keys %sum
' file.csv
XYZ = 1000
ZYX = 400

答え3

ここに解決策がありますawk

awk -F, '{for(a=1;a++<=NF;){
          if($a~/^55=/){l=$a}
          if($a~/^38=/){b[l]+=substr($a,4)}
         }}END{for(x in b){print x,"38="b[x]}}' inp
  • for(a=1;a++<=NF;){- カンマで区切られた各フィールドを繰り返します。
  • if($a~/^55=/){l=$a}- 次に始まるフィールドが見つかったら、55=それを変数に保存します。l
  • if($a~/^38=/){b[l]+=substr($a,4)}- 次から始まるフィールドが見つかったら、変数をキーとして使用して38=次の値を取得し、=配列に蓄積します。bl
  • }}END{for(x in b){print x,"38="b[x]}}- 配列の内容のみを印刷

答え4

どうですか?

awk -F, '
        {for (i=1; i<=NF; i++)  {split ($i, T, "=")
                                 if (T[1] == 55) IX = T[2]
                                 if (T[1] == 38) NM = T[2]
                                }
         SUM[IX] += NM
        }
END     {for (s in SUM) print "55=" s, "38=" SUM[s]
        }
' file
55=ZYX 38=400
55=XYZ 38=1000

すべてのフィールドを繰り返して関連フィールドを見つけ、配列Tに分割し、55見つかった場合はインデックスを抽出し、見つかった38場合は合計を抽出します。ループが終了すると、合計が実行されます。ENDセクションには、すべての要約値とそのインデックスが表示されます。

関連情報