Suma de valores en segundas columnas si la entrada de la primera columna es la misma en UNIX

Suma de valores en segundas columnas si la entrada de la primera columna es la misma en UNIX

Estoy intentando agregar un archivo que contiene los siguientes datos en UNIX. Necesito sumar las cantidades si la clave es la misma.

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

La salida debe ser la siguiente

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

Lo intenté con el siguiente comando, pero solo me da uniq

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

Respuesta1

Otra posible solución awkpodría ser:

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

El defecto es que no conservará su pedido. Entonces el resultado podría ser:

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

Respuesta2

Puedes hacer esto con awk:

#!/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(); }
'

donación

./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

Respuesta3

Aquí hay una manera en Perl. Llámalo así ./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{$_}});
}

Respuesta4

Esto utiliza Miller ( mlr) para calcular la suma del amountcampo sobre cada conjunto de registros agrupados por los campos Key, datey Time. Miller agregará la suma como un nuevo campo, amount_sumal final de la lista de campos, por lo que también reordenamos los campos y los volvemos a etiquetar.

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

Salida dada los datos de la pregunta:

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

Si no desea el encabezado en la salida, utilícelo mlrcon su --headerless-csv-outputopción.

información relacionada