Gerando relatórios com Bash e awk
1. Introdução ao awk e sua integração com Bash
awk é uma linguagem de programação criada na década de 1970 por Aho, Weinberger e Kernighan, projetada especificamente para processamento de texto e geração de relatórios. Sua sintaxe enxuta e poderosa permite extrair, transformar e formatar dados de arquivos estruturados como logs, CSVs e tabelas.
A integração entre Bash e awk é natural: enquanto o Bash gerencia fluxos de execução, arquivos e chamadas de sistema, o awk faz o trabalho pesado de análise textual. Um comando awk típico segue a estrutura:
awk 'padrão { ação }' arquivo
O padrão define quais linhas processar (ou é omitido para processar todas), e a ação determina o que fazer com cada linha correspondente. Essa simplicidade esconde um motor de processamento extremamente eficiente.
2. Fundamentos do awk para relatórios
No awk, cada linha de entrada é um registro e cada palavra ou coluna é um campo. Os separadores padrão são espaços ou tabulações, mas podem ser customizados.
Variáveis internas essenciais:
NR— número do registro atual (linha)NF— número de campos no registro atualFNR— número do registro no arquivo atual (útil com múltiplos arquivos)FS— separador de campos (padrão: espaço)OFS— separador de campos na saídaRS— separador de registros (padrão: newline)ORS— separador de registros na saída
Exemplo básico de leitura de um log:
# log.txt
2025-03-01 10:15:30 ERRO conexão recusada
2025-03-01 10:16:45 INFO requisição bem-sucedida
2025-03-01 10:17:10 ERRO timeout
awk '{ print NR, $1, $3, $4 }' log.txt
Saída:
1 2025-03-01 ERRO conexão
2 2025-03-01 INFO requisição
3 2025-03-01 ERRO timeout
3. Formatação de saída com printf
Para relatórios profissionais, o printf do awk oferece controle preciso sobre alinhamento, largura e justificação:
awk '{
printf "%-15s %-10s %-8s %s\n", $1, $2, $3, $4
}' log.txt
Onde %-15s significa: string justificada à esquerda com 15 caracteres de largura. Para números, usamos %d (inteiro) ou %.2f (float com 2 casas decimais).
Criando um cabeçalho formatado:
awk 'BEGIN {
printf "%-15s %-10s %-8s %-20s\n", "DATA", "HORA", "NIVEL", "MENSAGEM"
printf "%-15s %-10s %-8s %-20s\n", "---------------", "----------", "--------", "--------------------"
}
{ printf "%-15s %-10s %-8s %-20s\n", $1, $2, $3, $4 }' log.txt
4. Agregação e sumarização de dados
Arrays associativos no awk permitem acumular valores por chave. Exemplo de relatório de vendas:
# vendas.txt
ProdutoA 150.00
ProdutoB 230.50
ProdutoA 89.90
ProdutoC 450.00
ProdutoB 120.00
awk '{
total[$1] += $2
contagem[$1]++
}
END {
printf "%-12s %-8s %-10s\n", "PRODUTO", "QTDE", "TOTAL"
printf "%-12s %-8s %-10s\n", "------------", "--------", "----------"
for (produto in total) {
media = total[produto] / contagem[produto]
printf "%-12s %-8d R$ %7.2f\n", produto, contagem[produto], total[produto]
}
}' vendas.txt
Saída:
PRODUTO QTDE TOTAL
------------ -------- ----------
ProdutoA 2 R$ 239.90
ProdutoB 2 R$ 350.50
ProdutoC 1 R$ 450.00
5. Relatórios condicionais e filtragem avançada
Padrões compostos com operadores lógicos permitem filtrar dados com precisão:
# log_servidor.txt
2025-03-01 10:15:30 ERRO 500 conexão recusada
2025-03-01 10:16:45 INFO 200 requisição ok
2025-03-01 10:17:10 ERRO 503 timeout
2025-03-01 10:18:00 INFO 200 requisição ok
2025-03-01 10:19:30 ERRO 500 falha interna
awk '$3 == "ERRO" && $4 >= 500 {
erros[$4]++
}
END {
print "Relatório de Erros (HTTP >= 500)"
for (codigo in erros) {
printf "Código %d: %d ocorrências\n", codigo, erros[codigo]
}
}' log_servidor.txt
Para filtrar por intervalo de datas:
awk '$1 >= "2025-03-01" && $1 <= "2025-03-15" { print }' log.txt
6. Geração de relatórios em múltiplos formatos
CSV
awk 'BEGIN { OFS=","; print "DATA,HORA,NIVEL,MENSAGEM" }
{ print $1, $2, $3, $4 }' log.txt > relatorio.csv
HTML
awk 'BEGIN {
print "<html><body><table border='1'>"
print "<tr><th>Data</th><th>Hora</th><th>Nível</th><th>Mensagem</th></tr>"
}
{
printf "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", $1, $2, $3, $4
}
END { print "</table></body></html>" }' log.txt > relatorio.html
Markdown
awk 'BEGIN {
print "| Data | Hora | Nível | Mensagem |"
print "|------|------|-------|----------|"
}
{ printf "| %s | %s | %s | %s |\n", $1, $2, $3, $4 }' log.txt > relatorio.md
7. Scripts completos de relatórios automatizados
Um script Bash que encapsula a lógica awk com parâmetros flexíveis:
#!/bin/bash
# relatorio_log.sh - Gera relatório de logs
ARQUIVO="${1:-/var/log/syslog}"
NIVEL="${2:-ERRO}"
FORMATO="${3:-texto}"
if [ ! -f "$ARQUIVO" ]; then
echo "Arquivo não encontrado: $ARQUIVO"
exit 1
fi
case "$FORMATO" in
csv)
awk -v nivel="$NIVEL" 'BEGIN { OFS=","; print "LINHA,DATA,HORA,NIVEL,MENSAGEM" }
$3 == nivel { print NR, $1, $2, $3, $4 }' "$ARQUIVO" > "relatorio_${NIVEL}.csv"
echo "Relatório gerado: relatorio_${NIVEL}.csv"
;;
html)
awk -v nivel="$NIVEL" 'BEGIN {
print "<html><body><h2>Relatório de " nivel "</h2><table border='1'>"
print "<tr><th>Linha</th><th>Data</th><th>Hora</th><th>Mensagem</th></tr>"
}
$3 == nivel {
printf "<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", NR, $1, $2, $4
}
END { print "</table></body></html>" }' "$ARQUIVO" > "relatorio_${NIVEL}.html"
echo "Relatório gerado: relatorio_${NIVEL}.html"
;;
*)
awk -v nivel="$NIVEL" 'BEGIN {
printf "%-6s %-12s %-10s %-20s\n", "LINHA", "DATA", "HORA", "MENSAGEM"
printf "%-6s %-12s %-10s %-20s\n", "------", "------------", "----------", "--------------------"
}
$3 == nivel {
printf "%-6d %-12s %-10s %-20s\n", NR, $1, $2, $4
}' "$ARQUIVO"
;;
esac
Uso: ./relatorio_log.sh /var/log/syslog ERRO html
8. Boas práticas e otimização de desempenho
- Evite subprocessos: Não chame comandos externos dentro do awk se puder fazer com funções nativas
- Use BEGIN/END: Inicialize variáveis e formate saída nos blocos especiais
- Redirecione saídas: Use
>no shell em vez desystem("...")dentro do awk - Depuração: Use
awk -v debug=1e insiraif (debug) print "variavel=" variavelno código - Arquivos temporários: Para processamentos grandes, use
/tmpcom nomes únicos via$$
Exemplo de depuração:
awk -v debug=1 '{
if (debug) print "DEBUG: NR=" NR " NF=" NF > "/dev/stderr"
total += $2
}
END { print total }' dados.txt
Referências
- GNU Awk User's Guide — Documentação oficial completa do awk, cobrindo desde conceitos básicos até funções avançadas
- The AWK Programming Language (segunda edição) — Site oficial dos criadores do awk com exemplos históricos e técnicos
- Linux Journal: Generating Reports with awk — Artigo prático sobre geração de relatórios com awk em ambientes Linux
- Bash Hackers Wiki: awk — Guia colaborativo com exemplos de integração entre Bash e awk
- IBM Developer: awk tutorial — Tutorial introdutório da IBM sobre awk, com foco em processamento de logs e relatórios
- Stack Overflow: awk tag — Comunidade ativa com milhares de perguntas e respostas sobre awk, incluindo geração de relatórios
- Conventional Commits: awk examples — Repositório de exemplos práticos de awk para automação de relatórios