
Tenho vários arquivos CSV com conteúdo semelhante. Os valores geralmente são separados por vírgula e têm esta aparência.
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 sou um usuário relativamente novo do Linux...) é a soma de cada produto (Coluna 1), inserida como uma coluna nº 2. Posso fazer algo assim
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, no formato deste:
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
...
Tenho usado um pouco de sed e awk ultimamente, mas minhas tentativas geralmente geram erros (como: tentativa de usar um valor escalar como array).
A ordem das linhas não é minha preocupação, mas presumo 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 a @KM. Cheguei ao lugar onde posso fazer o que quero em 3 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?
Responder1
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, a primeira coluna do primeiro arquivo com a primeira coluna do segundo (pense em "chaves"); canalize-o awk
e imprima colunas reordenadas, usando ,
como separador de campo ( -F
)ecomo o Separador de 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