awk avançado
Esta aula explora recursos avançados do awk, incluindo variáveis, condicionais, loops e os blocos especiais BEGIN/END, com foco na geração de relatórios complexos. O conteúdo é prático e progressivo, preparando o aluno para manipular arquivos de texto de forma profissional.
O awk é uma ferramenta poderosa para processamento de texto em shell script. Nesta aula, vamos aprofundar o uso de variáveis, estruturas de controle (condicionais e loops) e os blocos especiais BEGIN e END, que permitem executar ações antes e depois do processamento principal. Ao final, você será capaz de gerar relatórios complexos diretamente da linha de comando ou em scripts.
Dominar esses conceitos é essencial para automatizar análises de logs, extrair dados de arquivos CSV e criar resumos estatísticos. Vamos começar!
Variáveis e operações
No awk, variáveis podem ser definidas pelo usuário ou herdadas do shell. Elas não precisam ser declaradas e seu tipo é inferido dinamicamente. Variáveis numéricas são inicializadas com zero, e strings com vazio. Você pode usar variáveis para armazenar contagens, somas, valores de campo e resultados intermediários.
Operações aritméticas como +, -, *, / e % funcionam normalmente. Para strings, a concatenação é feita justapondo-as. Exemplo: total = total + $1 ou nome = $1 " " $2. Também é possível usar operadores de atribuição como +=, -=, etc.
# Exemplo: somar o primeiro campo de cada linha
awk '{ soma += $1 } END { print "Soma:", soma }' dados.txt
# Usando variável definida pelo usuário
awk -v fator=2 '{ print $1 * fator }' dados.txt
Condicionais e loops
O awk suporta as estruturas condicionais if, if-else e if-else if-else, além de operadores lógicos (&&, ||, !). A sintaxe é similar ao C. Os comandos podem ser agrupados com chaves. Exemplo: if ($1 > 10) { print $1 } else { print "menor" }.
Os loops disponíveis são while, do-while e for. O for pode ser usado tanto no estilo C (for (i=1; i<=NF; i++)) quanto para percorrer arrays (for (i in array)). Os comandos break e continue funcionam como esperado.
# Usando if para filtrar linhas
awk '{ if ($3 > 100) print $0 }' vendas.txt
# Loop for para somar todos os campos de cada linha
awk '{ soma=0; for(i=1; i<=NF; i++) soma+=$i; print soma }' dados.txt
BEGIN e END
Os blocos BEGIN e END são especiais: o BEGIN é executado antes de qualquer linha ser lida, ideal para inicializar variáveis, imprimir cabeçalhos ou configurar separadores. O END é executado após o processamento de todas as linhas, usado para resumos, totais e relatórios finais.
Você pode ter múltiplos blocos BEGIN e END, e eles serão executados na ordem em que aparecem. É comum usar BEGIN para definir o separador de campo com FS ou OFS. Exemplo: BEGIN { FS=","; OFS="|" }.
# Exemplo com BEGIN e END
awk 'BEGIN { print "Início do processamento" }
{ total += $1 }
END { print "Total:", total }' numeros.txt
# Configurando separador no BEGIN
awk 'BEGIN { FS=":"; OFS="-" } { print $1, $3 }' /etc/passwd
Relatórios
Combinando os recursos anteriores, podemos gerar relatórios formatados. O awk permite formatar saída com printf, similar ao C, controlando largura de campos, alinhamento e casas decimais. Você pode criar tabelas, resumos estatísticos e até gráficos simples com caracteres.
Um relatório típico pode incluir cabeçalho (no BEGIN), processamento linha a linha com acumulação de dados, e rodapé com totais (no END). Use arrays associativos para agrupar dados por chave, como por departamento ou mês.
# Relatório de vendas por vendedor
awk 'BEGIN { printf "%-15s %10s\n", "Vendedor", "Total"
printf "%s\n", "-------------------------" }
{ vendas[$1] += $2 }
END { for (v in vendas) printf "%-15s %10.2f\n", v, vendas[v] }' vendas.csv
Boas práticas
Use -v para passar variáveis do shell para o awk, evitando problemas com aspas. Comente blocos complexos. Prefira printf para formatação precisa. Teste com pequenos conjuntos de dados antes de processar arquivos grandes.
Referências
- GNU Awk User's Guide
- IBM: awk command
- Linux man page: awk
- Tutorialspoint: AWK Tutorial
- The Geek Stuff: AWK Array Examples
Exercícios
- Escreva um comando awk que some todos os números do primeiro campo de um arquivo, ignorando linhas que começam com #.
- Crie um relatório que exiba, para cada mês (campo 2 no formato "2024-01"), o total do campo 3. Use arrays associativos.
- Use o bloco BEGIN para definir o separador de campo como vírgula e imprimir um cabeçalho "Nome,Idade".
- Escreva um comando awk que use um loop para imprimir cada campo de uma linha em linhas separadas.
- Gere um relatório que mostre a média do campo 2 para cada valor único do campo 1.
awk '!/^#/ { soma += $1 } END { print soma }' arquivo.txt
awk '{ total[$2] += $3 } END { for (mes in total) print mes, total[mes] }' dados.csv
awk 'BEGIN { FS=","; print "Nome,Idade" } { print $1 "," $2 }' pessoas.csv
awk '{ for(i=1; i<=NF; i++) print $i }' arquivo.txt
awk '{ soma[$1] += $2; cont[$1]++ } END { for (k in soma) print k, soma[k]/cont[k] }' dados.txt