Addition von Werten in der zweiten Spalte, wenn der erste Spalteneintrag unter UNIX derselbe ist

Addition von Werten in der zweiten Spalte, wenn der erste Spalteneintrag unter UNIX derselbe ist

Ich versuche, eine Datei mit den folgenden Daten unter UNIX zu aggregieren. Ich muss die Beträge addieren, wenn der Schlüssel derselbe ist.

Key,amount,date,Time
abc-xyz-12234,45,15-08-91,23:00
pqr-vgh-5241,15,15-08-91,21:00
abc-xyz-12234,35,15-08-91,23:00
pqr-vgh-5241,24,15-08-91,21:00
abc-xyz-12234,655,15-08-91,23:00
lkj-erf-8542,281,15-08-91,10:00
pqr-vgh-5241,40,15-08-91,21:00

Die Ausgabe sollte wie folgt aussehen

abc-xyz-12234,735,15-08-91,23:00
pqr-vgh-5241,79,15-08-91,21:00
lkj-erf-8542,281,15-08-91,10:00

Ich habe es mit dem folgenden Befehl versucht, aber es gibt mir nur uniq

cat file | grep "abc-xyz-12234" | uniq

Antwort1

Eine weitere mögliche Lösung awkkönnte sein:

awk 'BEGIN { FS = OFS = "," }
     NR != 1 { y[$1] += $2; $2 = y[$1]; x[$1] = $0; }
     END { for (i in x) { print x[i]; } }' file

Der Fehler besteht darin, dass Ihre Bestellung nicht erhalten bleibt. Das Ergebnis könnte also sein:

pqr-vgh-5241,79,15-08-91,21:00
abc-xyz-12234,735,15-08-91,23:00
lkj-erf-8542,281,15-08-91,10:00

Antwort2

Dies können Sie mit awk tun:

#!/bin/sh
sort | awk -F, '
function result() {
    if ( key != "" ) {
            printf "%s,%d,%s\n", key, value, datetime;
    }
}
BEGIN { key = ""; value = 0; datetime = ""; }
$2 ~ /^[0-9]+/ {
    if ( $1 == key ) {
            value += $2;
    } else {
            result();
            key = $1;
            value = $2;
            datetime = $3 "," $4;
    }
}
END { result(); }
'

Geben

./foo <input
abc-xyz-12234,735,15-08-91,23:00
lkj-erf-8542,281,15-08-91,10:00
pqr-vgh-5241,79,15-08-91,21:00

Antwort3

Hier ist eine Möglichkeit in Perl. Nennen Sie es so ./script file.ext:

use warnings;
use strict;

my %data;
my @order;

while (<>){
    next if $. == 1;
    my @line = split /,/;
    if (defined $data{$line[0]}){
        $data{$line[0]}->[1] += $line[1];
    }
    else {
        $data{$line[0]} = \@line;
        push @order, $line[0];
    }
}

for (@order){
    print join(',', @{$data{$_}});
}

Antwort4

Dabei wird Miller ( mlr) verwendet, um die Summe der amountFelder für alle Datensätze zu berechnen, die nach den Feldern Key, date, und gruppiert sind Time. Miller fügt die Summe als neues Feld , amount_sumam Ende der Liste der Felder hinzu, daher ordnen wir die Felder auch neu an und benennen sie neu.

mlr --csv \
    stats1 -a sum -f amount -g Key,date,Time then \
    reorder -f Key,amount_sum then \
    label Key,amount file

Ausgabe unter Berücksichtigung der Daten in der Frage:

Key,amount,date,Time
abc-xyz-12234,735,15-08-91,23:00
pqr-vgh-5241,79,15-08-91,21:00
lkj-erf-8542,281,15-08-91,10:00

Wenn Sie den Header nicht in der Ausgabe haben möchten, verwenden Sie ihn mlrmit der entsprechenden --headerless-csv-outputOption.

verwandte Informationen