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
awk
leu 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,next
dizawk
para pular o resto dos comandos e começar de novo com o próximo registro.Note que não é necessário inicializar
s
para 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/s
Se chegarmos a este comando, estamos processando o segundo arquivo. Isso significa que
s
agora 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:
-
%d
formata números como números inteiros. Se o número for realmente ponto flutuante, ele será truncado para um inteiro -
%f
formata números como ponto flutuante. Também é possível especificar larguras e casas decimais como, por exemplo,%5.2f
. -
%e
fornece 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