Como você realizaria 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, wc -l
mas isso só imprime o número de linhas, não as avalia.
Como posso avaliar cada linha do awk?
Responder1
Uma abordagem básica, usando seu exemplo:
awk '{sum+=$1} END {print sum}' file
Responder2
Se você tiver controle sobre o programa awk, faça a adição dentro do awk como mostra @jasonwryan.
Se você realmente deseja somar os números que o awk exibe, canalize a saída para um destes:
| { tr '\n' '+' ; echo 0; } | bc
| { while read line; do ((sum+=line)); done; echo $sum; }
No segundo exemplo, o comando echo está entre chaves de agrupamento porque o bash executa o pipeline em um subshell, portanto, alterações na variável $sum não existirão quando o subshell sair.
Responder3
O Bash não consegue lidar com decimais, mas pode lidar com a manipulação simples de números inteiros, você só precisa usar um truque comosubstituição de processopara 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;
Existe n=0
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 direta seja usar gawk
para fazer o cálculo, você também pode usar uma linha única Perl:
awk '{print $1}' foo | perl -lne '$k+=$_;END{print "$k"};'
O -l
sinalizador remove novas linhas ( chomp
) e adiciona uma ao final de cada string impressa, o que -n
significa ler o arquivo linha por linha, salvando cada linha como $_
e executar o script fornecido com -e
.
Ou faça tudo em Perl:
perl -alne '$k+=$F[0];END{print "$k"};' foo
O -a
sinalizador 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 @F
matriz, portanto o primeiro campo é $F[0]
.
Responder4
O método de uma linha que normalmente uso para totais simples como este é canalizar para xargs para obter toda a saída do awk em uma linha, depois através do sed para transformar espaços em pontos positivos e, finalmente, em bc para fazer o cálculo:
cat foo | awk '{print $1} | xargs | sed -e 's/ /+/g' | bc