Para criar a tabela com uma única chamada para awk :
$ awk 'FNR==NR{s+=$2;next;} {printf "%s\t%s\t%s%%\n",$1,$2,100*$2/s}' data data
foo 10 10%
bar 20 20%
oof 50 50%
rab 20 20%
Como funciona
O arquivo data é fornecido como um argumento para awk duas vezes. Conseqüentemente, ele será lido duas vezes, a primeira vez para obter o total, que é armazenado na variável s , e o segundo para imprimir a saída. Olhando os comandos com mais detalhes:
-
FNR==NR{s+=$2;next;}NR é o número total de registros (linhas) que
awkleu e FNR é o número de registros lidos até o momento a partir do arquivo atual. Conseqüentemente, quandoFNR==NR, estamos lendo o primeiro arquivo. Quando isso acontece, a variávelsé incrementada pelo valor na segunda coluna. Então,nextdizawkpara pular o resto dos comandos e começar de novo com o próximo registro.Note que não é necessário inicializar
spara zero. Emawk, todas as variáveis numéricas são, por padrão, inicializadas como zero. -
printf "%s\t%s\t%s%%\n",$1,$2,100*$2/sSe chegarmos a este comando, estamos processando o segundo arquivo. Isso significa que
sagora contém o total da coluna 2. Portanto, imprimimos a coluna 1, a coluna 2 e a porcentagem,100*$2/s.
Opções de formato de saída
Com printf , o controle detalhado do formato de saída é possível. O comando acima usa o especificador de formato %s , que funciona para strings, inteiros e flutuantes. Três outras opções que podem ser úteis aqui são:
-
%dformata números como números inteiros. Se o número for realmente ponto flutuante, ele será truncado para um inteiro -
%fformata números como ponto flutuante. Também é possível especificar larguras e casas decimais como, por exemplo,%5.2f. -
%efornece notação exponencial. Isso seria útil se alguns números fossem excepcionalmente grandes ou pequenos.
Faça uma função de shell
Se você for usar isso mais de uma vez, é inconveniente digitar um comando longo. Em vez disso, crie uma função ou um script para burlar o comando.
Para criar uma função chamada totals , execute o comando:
$ totals() { awk 'FNR==NR{s+=$2;next;} {printf "%s\t%s\t%s%%\n",$1,$2,100*$2/s}' "$1" "$1"; }
Com essa função definida, as porcentagens de um arquivo de dados chamado data podem ser encontradas executando:
$ totals data
Para tornar a definição de totals permanent, coloque-a no arquivo ~/.bashrc .
Crie um script de shell
Se você preferir um script, crie um arquivo chamado totals.sh com o conteúdo:
#!/bin/sh
awk 'FNR==NR{s+=$2;next;} {printf "%s\t%s\t%s%%\n",$1,$2,100*$2/s}' "$1" "$1"
Para obter as porcentagens de um arquivo de dados chamado data , execute:
sh totals.sh data