Resumindo uma matriz dentro do awk?

6

Eu tenho o seguinte trecho de código:

sum1=
sum2=    
declare -a a
echo $temp | awk '{split($0,a,","); name=a[1] ; for(i=2;i<=4;i++) sum1+=a[i] ; for(i=5;i<=7;i++) sum2+=a[i] }'

Este código não está funcionando. Aqui temp é uma string do tipo:

abc,1,2,3,4,5,6

Eu sou iniciante e preciso de algumas sugestões. Na verdade, estou analisando dados de um arquivo. O arquivo de entrada é como:

abc,1,2,3,4,5,6
de,3,5,7,8,4,2
xyz,6,5,3,7,8,2

Estou lendo usando

while  read temp
do
 #do something
done < sample.csv

A saída esperada é da seguinte forma:

Name   Sum1  Sum2
abc      6    15
de      15    14
xyz     14    17 
    
por user2179293 16.09.2013 / 17:10

3 respostas

6

Configurando $ temp

Primeiro, certifique-se de ter configurado a variável $temp corretamente:

$ temp="abc,1,2,3,4,5,6"
$ echo "$temp"
abc,1,2,3,4,5,6

Exemplo simples

Eu usei a seguinte abordagem para fazer isso:

$ echo "$temp" | tr ',' '\n' | grep -v abc | awk '{sum+=$1};END{print sum}'
21

Seu exemplo

Em relação à sua abordagem, você esqueceu de imprimir os arrays acumulados com um bloco END{...} :

$ echo "$temp" | awk '{split($0,a,","); name=a[1]
      for(i=2;i<=4;i++) sum1+=a[i] ; for(i=5;i<=7;i++) sum2+=a[i] }
      END{print sum1; print sum2}'
6
15

Salvando para depois

O Awk não tem um método para injetar resultados no shell do pai de onde ele foi chamado, então você terá que ser um pouco esperto e salvar seus resultados em um array no Bash.

Exemplo

$ myarr=($(echo "$temp" | awk '{split($0,a,","); name=a[1]
      for(i=2;i<=4;i++) sum1+=a[i] ; for(i=5;i<=7;i++) sum2+=a[i] }
      END{ print sum1; print sum2}'))

O texto acima está fazendo isso:

$ myarr=($(...awk command...))

Isso resultará em seus valores de sum1 e sum2 sendo salvos na matriz $myarr .

Acessando o array $ myarr

Eles são acessíveis assim:

$ echo "${myarr[@]}"
6 15

$ echo "${myarr[0]}"
6

$ echo "${myarr[1]}"
15
    
por 16.09.2013 / 17:20
11

Tente isto:

$ awk -F',' 'BEGIN{OFS="\t";print "Name","Sum1","Sum2"}
                  {print $1,$2+$3+$4,$5+$6+$7}' sample.csv 
Name        Sum1 Sum2
abc         6    15
de          15   14
xyz         14   17

Não há necessidade de seu loop bash, você pode fazer tudo em awk . A opção -F permite que você defina o separador de campos de entrada, neste caso , , para que você não precise dividir explicitamente a linha. Como awk lê arquivos linha por linha, você também não precisa ler o arquivo em bash .

O bloco BEGIN{} é executado antes de ler a primeira linha e apenas imprime o cabeçalho e define o separador de saída ( OFS ) para uma guia. Como os campos já estão separados, tudo o que você precisa fazer é somar os campos 2-4 e 5-7 e imprimi-los para cada linha.

    
por 16.09.2013 / 17:51
3

Bash

#!/usr/bin/env bash
printf "%-5s\t%s\t%s\n" Name Sum1 Sum2
while IFS=, read -a Arr
do
        (( Grp1 = Arr[1] + Arr[2] + Arr[3] ))
        (( Grp2 = Arr[4] + Arr[5] + Arr[6] ))

        printf "%-5s\t%d\t%d\n" ${Arr[0]} $Grp1 $Grp2

done < input.txt

Resultado

root@ubuntu:~# bash  parse.sh
Name    Sum1    Sum2
abc     6       15
de      15      14
xyz     14      17

Graças a @ 1_CR para truques aritméticos para o elemento array

    
por 16.09.2013 / 18:05