AWK, Soma da categoria

1

Tenho toneladas de arquivos CSV com conteúdo semelhante. Os valores geralmente são separados por vírgula e eles se parecem com isso.

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

O que estou tentando realizar, com o AWK (porque acredito que o SED não é a ferramenta certa para tais operações, mas eu sou usuário Linux relativamente novo ...) é a soma de cada produto (coluna 1), insterted como uma coluna nr 2. Eu posso fazer algo parecido com isto

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

para obter esses valores (somas)

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

mas ainda não tenho ideia de como inseri-los como uma segunda coluna no arquivo original, da seguinte forma:

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

Eu tenho usado um pouco de sed e awk ultimamente, mas minhas tentativas normalmente me pegam Error (como: tentativa de usar um valor escalar como array).

A ordem das linhas não é minha preocupação, mas suponho que poderei usar a resposta como um comando de arquivo em lote.

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

EDITAR
Obrigado pelo @KM. Cheguei ao local, onde posso fazer o que quiser em três etapas.

1 passo:

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

2º passo:

$ 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, apenas rm sum*.* . Existe uma maneira de executá-lo como um comando do terminal? Ou fora disso?

    
por Je.dno 16.05.2016 / 16:59

1 resposta

1

Salve a soma em um arquivo chamado sum , classificado

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

Junte os dois arquivos, primeira coluna do primeiro arquivo com a primeira coluna do segundo (pense em "chaves"); canalize-o para awk e imprima colunas reordenadas, usando , como separador de campo ( -F ) e como o Separador do campo de saída ( -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
    
por 16.05.2016 / 18:09