Como adicionar cada saída do awk

5

Como você executaria a adição na saída de cada linha do awk?

Por exemplo

cat foo | awk '{print $1}
42
42
42

Estou procurando a resposta para 42 + 42 + 42 (126).

Estou tentando escrever um loop for para fazer isso, mas deve haver uma maneira mais simples

#Not Working, and way too complex
cat foo |awk  '{ print $1 }'|for i in $1 do; foo=$(( foo+$(i) )) done| echo $foo

Eu poderia canalizar para wc -l , mas isso só imprime o número de linhas, mas não as avalia.

Como posso avaliar cada linha do awk?

    
por spuder 30.09.2013 / 21:38

4 respostas

11

Uma abordagem básica, usando o seu exemplo:

awk '{sum+=$1} END {print sum}' file
    
por 30.09.2013 / 21:52
4

Se você tiver controle sobre o programa awk, faça a adição em awk como @jasonwryan mostra.

Se você realmente quiser resumir os números que o awk cospe, coloque a saída em um destes:

| { tr '\n' '+' ; echo 0; } | bc
| { while read line; do ((sum+=line)); done; echo $sum; }

No segundo exemplo, o comando echo está dentro das chaves de agrupamento porque o bash executa o pipeline em uma subshell, portanto, as alterações na variável $ sum não existirão quando a subshell sair.

    
por 30.09.2013 / 22:48
1

O Bash não pode lidar com decimais, mas pode manipular simples manipulações de inteiros, você só precisa usar um truque como substituição de processos para tornar a variável acessível fora do loop:

n=0;while read i; do let n+=$i; done < <(awk '{print $1}' foo); echo $n;

ou

n=0;while read i; do n=$((n+i)); done < <(awk '{print $1}' foo); echo $n;

O n=0 está lá apenas para garantir que $n seja sempre 0, caso contrário, executar esses comandos uma segunda vez retornaria 252 em vez de 126.

Embora a maneira mais simples seja usar gawk para fazer o cálculo, você também pode usar uma linha de uma linha Perl:

awk '{print $1}' foo | perl -lne '$k+=$_;END{print "$k"};'

O -l flag remove novas linhas ( chomp ) e adiciona uma ao final de cada string impressa, o -n significa ler o arquivo linha por linha, salvando cada linha como $_ e executando o script fornecido com -e .

Ou faça tudo em Perl:

perl -alne '$k+=$F[0];END{print "$k"};' foo

O sinalizador -a para Perl ativa a divisão automática de linha (como gawk ). Por padrão, os campos são divididos em espaços, mas isso pode ser alterado usando -F . Os campos resultantes são salvos como a matriz @F , portanto, o primeiro campo é $F[0] .

    
por 01.10.2013 / 03:53
0

O método one-liner que costumo usar para totais simples como este é canalizar para xargs para obter todas as saídas do awk em uma linha, depois através do sed para transformar espaços em vantagens, e finalmente em bc para fazer o cálculo:

cat foo | awk '{print $1} | xargs | sed -e 's/ /+/g' | bc
    
por 01.10.2013 / 04:24

Tags