Uma abordagem básica, usando o seu exemplo:
awk '{sum+=$1} END {print sum}' file
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?
Uma abordagem básica, usando o seu exemplo:
awk '{sum+=$1} END {print sum}' file
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.
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]
.
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
Tags awk