Como adicionar cada saída do awk

Como adicionar cada saída do awk

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 -lmas 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=0apenas para garantir que $nseja sempre 0; caso contrário, executar esses comandos uma segunda vez retornaria 252 em vez de 126.


Embora a maneira mais direta seja usar gawkpara fazer o cálculo, você também pode usar uma linha única Perl:

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

O -lsinalizador remove novas linhas ( chomp) e adiciona uma ao final de cada string impressa, o que -nsignifica 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 -asinalizador 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 @Fmatriz, 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

informação relacionada