steeldriver meio que me bateu nisso, mas eu inventei
perl -F'[=,]' -lane '
%row = @F;
$sum{$row{55}} += $row{38};
}{
print "$_ = $sum{$_}" for keys %sum
' file.csv
XYZ = 1000
ZYX = 400
Estou usando o bash para criar um script para localizar, agrupar e somar campos em um arquivo CSV. Cada linha terá campos separados por vírgula com cada campo seguindo uma convenção semelhante. Para cada campo separado por vírgulas, existe um valor numérico, depois um sinal de igual (=) e, em seguida, um valor alfanumérico. O "(número)=" pode ou não estar presente em uma linha e, se presente, a posição do campo pode variar, mas aparece apenas uma vez na linha. Além disso, o valor após o sinal de igual varia em comprimento.
Um exemplo do meu objetivo será o melhor. Arquivo CSV:
35=D,11=ABCD1,1=ABC,55=XYZ,38=100,40=P,18=M,54=1,59=0,10=111
35=D,11=ABCD2,1=ABC,55=XYZ,40=P,18=M,38=200,54=1,44=10.00,59=0,10=133
35=D,11=ABCD3,1=ABC,55=XYZ,40=P,18=M B,54=1,38=300,44=10.00,59=0,110=200,10=113
35=D,11=ABCD4,1=ABC,55=XYZ,38=400,40=P,18=M B F,54=1,44=10.00,59=0,110=300,10=144
35=D,11=ABCD5,1=ABC,55=ZYX,38=300,40=2,54=1,44=10.00,59=3,10=132
35=D,11=ABCD6,1=ABC,55=ZYX,38=100,40=1,18=C,54=2,59=3,10=131
Eu gostaria de ter um script que identificasse cada campo que começa com "38=" e, em seguida, some cada valor numérico que segue o "=" e agrupe por cada "55=". Haverá um "38=" e um "55=" em cada linha.
A saída usando o arquivo acima seria (o tipo é opcional):
55=XYZ 38=1000
55=ZYX 38=400
steeldriver meio que me bateu nisso, mas eu inventei
perl -F'[=,]' -lane '
%row = @F;
$sum{$row{55}} += $row{38};
}{
print "$_ = $sum{$_}" for keys %sum
' file.csv
XYZ = 1000
ZYX = 400
Aqui está uma solução awk
.
awk -F, '{for(a=1;a++<=NF;){
if($a~/^55=/){l=$a}
if($a~/^38=/){b[l]+=substr($a,4)}
}}END{for(x in b){print x,"38="b[x]}}' inp
for(a=1;a++<=NF;){
- percorre cada campo delimitado por vírgulas if($a~/^55=/){l=$a}
- se encontrarmos um campo que comece com 55=
, armazene-o na variável l
if($a~/^38=/){b[l]+=substr($a,4)}
- se encontrarmos um campo começando com 38=
, pegue o valor depois de =
e acumule-o na matriz b
, usando a variável l
como chave }}END{for(x in b){print x,"38="b[x]}}
- apenas imprima o conteúdo da matriz Que tal
awk -F, '
{for (i=1; i<=NF; i++) {split ($i, T, "=")
if (T[1] == 55) IX = T[2]
if (T[1] == 38) NM = T[2]
}
SUM[IX] += NM
}
END {for (s in SUM) print "55=" s, "38=" SUM[s]
}
' file
55=ZYX 38=400
55=XYZ 38=1000
Percorra todos os campos para encontrar os campos relevantes, divididos em T
array, se 55
encontrado, extrair o índice, se 38
for encontrado, extrair summand. Após o loop, faça o somatório. Na seção END
, exiba todos os valores somados com seus índices.