AWK, Suma de categoría

AWK, Suma de categoría

Tengo toneladas de archivos CSV con contenido similar. Los valores suelen estar separados por comas y tienen este aspecto.

product_a,  domestic,   500
product_a,  abroad,     15
product_b,  domestic,   313
product_b,  abroad,     35
product_c,  domestic,   411
product_c,  abroad,     84
product_d,  domestic,   25
product_d,  abroad,     2
...

Lo que estoy tratando de lograr con AWK (porque creo que SED no es la herramienta adecuada para este tipo de operaciones, pero soy un usuario relativamente nuevo de Linux...) es la suma de cada producto (Columna 1), insertada como una columna. n° 2. Puedo hacer algo como esto

awk -F, '{a[$1]+=$3;}END{for (i in a)print i", "a[i];}' filename

para obtener esos valores (sumas)

product_a,  515
product_b,  348
product_c,  495
product_d,  27
...

pero todavía no tengo idea de cómo insertarlos como una segunda columna en el archivo original, en una forma como esta:

product_a,  515, domestic,  500
product_a,  515, abroad,    15
product_b,  348, domestic,  313
product_b,  348, abroad,    35
product_c,  495, domestic,  411
product_c,  495, abroad,    84
product_d,  27,  domestic,  25
product_d,  27,  abroad,    2
...

He estado usando un poco de sed y awk últimamente, pero mis intentos generalmente me dan un error (como: intento usar un valor escalar como matriz).

El orden de las filas no es de mi incumbencia, pero supongo que podré usar la respuesta como un comando de archivo por lotes.

$ for f in *.csv; do
  That Shiny Enigmatic Command > tmp && mv tmp $f
  done

EDITAR
Gracias a @KM. Llegué al lugar donde puedo hacer lo que quiero en 3 pasos.

1 paso:

$ for f in *.csv; do 
awk -F, '{a[$1]+=$3;}END{for (i in a)print i", "a[i];}' $f | sort > sum$f
done

2do paso:

$ for f in [^sum]*.csv; do 
join -t ',' $f sum$f | awk -F, '{print $1"," $4"," $2"," $3}' > tmp && mv tmp $f; 
done

Para eventualmente simplemente rm sum*.*. ¿Hay alguna forma de ejecutarlo como un comando desde la terminal? ¿O fuera de él?

Respuesta1

Guarde la suma en un archivo llamado sum, ordenado

awk -F, '{a[$1]+=$3;}END{for (i in a)print i", "a[i];}' filename | sort > sum

cat sum 
product_a, 515
product_b, 348
product_c, 495
product_d, 27

Une los dos archivos, la primera columna del primer archivo con la primera columna del segundo (piensa en "claves"); canalícelo awke imprima columnas reordenadas, utilizando ,como separador de campo ( -F)ycomo separador de campo de salida ( -OFS)

join -t ','  -1 1 -2 1 filename sum | awk -F, -OFS=, {'print $1,$4,$2,$3}'

product_a,  515,  domestic,  500
product_a,  515,  abroad,    15
product_b,  348,  domestic,  313
product_b,  348,  abroad,    35
product_c,  495,  domestic,  411
product_c,  495,  abroad,    84
product_d,  27,   domestic,  25
product_d,  27,   abroad,    2

información relacionada