Awk: processamento de colunas e relatórios

1. Introdução ao Awk

Awk é uma linguagem de programação projetada especificamente para processamento de texto e geração de relatórios. Criada em 1977 por Aho, Weinberger e Kernighan (daí o nome Awk), ela se destaca no ecossistema Shell por sua capacidade de trabalhar com dados estruturados em linhas e colunas de forma elegante e concisa.

A estrutura fundamental do Awk segue o padrão pattern { action }. O programa lê o arquivo linha por linha, aplica os padrões especificados e executa as ações correspondentes quando há correspondência. Isso torna o Awk ideal para filtragem, transformação e sumarização de dados textuais.

A invocação pode ser feita de três formas: scripts inline diretamente no terminal (awk 'programa' arquivo), scripts em arquivos .awk separados, ou como filtro em pipes (comando | awk 'programa').

2. Sintaxe fundamental e campos

O Awk trata automaticamente cada linha como um registro e cada palavra delimitada por espaços como um campo. As variáveis especiais são essenciais:

  • $0 — linha completa
  • $1, $2, etc. — campos individuais
  • NF — número de campos na linha atual
  • NR — número do registro atual (linha)
  • FS — separador de campos (padrão: espaço)
  • OFS — separador de saída (padrão: espaço)
# Imprimir primeira e terceira colunas de um arquivo
awk '{ print $1, $3 }' dados.txt

# Reordenar campos: imprimir coluna 3, depois coluna 1
awk '{ print $3, $1 }' dados.txt

# Filtrar linhas com mais de 3 campos
awk 'NF > 3 { print $0 }' dados.txt

Para delimitadores customizados, use -F:

# Arquivo CSV com delimitador ponto-e-vírgula
awk -F';' '{ print $1, $2 }' dados.csv

# Configuração inline do FS
awk 'BEGIN { FS=":" } { print $1, $3 }' /etc/passwd

3. Padrões (patterns) e filtragem de linhas

Os padrões permitem selecionar linhas específicas para processamento. Expressões regulares são amplamente suportadas:

# Linhas que contêm "erro"
awk '/erro/ { print $0 }' log.txt

# Linhas que NÃO contêm "erro"
awk '!/erro/ { print $0 }' log.txt

# Linhas onde o terceiro campo é maior que 100
awk '$3 > 100 { print $1, $3 }' vendas.txt

# Décima linha do arquivo
awk 'NR == 10 { print $0 }' arquivo.txt

# Padrões compostos
awk '$3 > 50 && $4 < 200 { print $0 }' dados.txt
awk '$1 == "João" || $2 == "Maria" { print $0 }' contatos.txt

Os blocos especiais BEGIN e END executam ações antes de processar qualquer linha e após processar todas as linhas, respectivamente:

awk 'BEGIN { print "Início do relatório" } { print $0 } END { print "Fim do relatório" }' dados.txt

4. Ações e comandos internos

O print é o comando de saída mais simples, enquanto printf oferece formatação precisa:

# Formatação com printf
awk '{ printf "%-20s %5d\n", $1, $2 }' dados.txt

Controle de fluxo dentro das ações:

# If/else
awk '{ if ($3 > 100) print $1, "ALTO"; else print $1, "BAIXO" }' dados.txt

# Loop for
awk '{ for (i = 1; i <= NF; i++) print $i }' dados.txt

# While
awk '{ i = 1; while (i <= NF) { print $i; i++ } }' dados.txt

Arrays associativos são poderosos para agrupamento:

# Contar ocorrências de cada valor na primeira coluna
awk '{ contagem[$1]++ } END { for (item in contagem) print item, contagem[item] }' dados.txt

5. Funções internas de string e matemática

Funções de string:

# length() - comprimento da string
awk '{ print $1, length($1) }' palavras.txt

# sub() e gsub() - substituição
awk '{ sub("antigo", "novo"); print }' arquivo.txt
awk '{ gsub(",", ";"); print }' dados.csv

# split() - dividir string em array
awk '{ n = split($0, arr, ":"); print arr[1], arr[3] }' /etc/passwd

# toupper() e tolower()
awk '{ print toupper($1), tolower($2) }' dados.txt

Funções matemáticas:

# int() - parte inteira
awk '{ print int($1) }' numeros.txt

# sqrt() - raiz quadrada
awk '{ print sqrt($1) }' numeros.txt

# sprintf() - formatação para string
awk '{ valor = sprintf("%.2f", $1); print valor }' dados.txt

6. Geração de relatórios estruturados

Combinando BEGIN, END e acumuladores, criamos relatórios completos:

awk '
BEGIN {
    print "==================================="
    print "RELATÓRIO DE VENDAS"
    print "==================================="
    print "Produto     | Qtd | Valor"
    print "-----------------------------------"
}
{
    printf "%-12s | %3d | %6.2f\n", $1, $2, $3
    total_qtd += $2
    total_valor += $3
}
END {
    print "-----------------------------------"
    printf "TOTAL       | %3d | %6.2f\n", total_qtd, total_valor
    print "==================================="
}' vendas.txt

Médias por grupo:

awk '
{
    soma[$1] += $2
    contagem[$1]++
}
END {
    for (grupo in soma) {
        media = soma[grupo] / contagem[grupo]
        printf "Grupo %s: média = %.2f\n", grupo, media
    }
}' dados.txt

7. Integração com outras ferramentas Shell

Awk brilha em pipelines, combinando com grep, sort, uniq e outras ferramentas:

# Análise de logs: contar IPs únicos
grep "ERROR" access.log | awk '{ print $1 }' | sort | uniq -c | sort -rn | head -10

# Processar saída de comandos do sistema
ps aux | awk '$3 > 50 { print $1, $2, $3 "%" }'

# Passar variáveis do Shell com -v
limite=100
awk -v lim="$limite" '$3 > lim { print $0 }' dados.txt

Exemplo prático: sumarizar um arquivo CSV de vendas:

# Arquivo vendas.csv: produto,quantidade,preco,data
awk -F',' '
NR > 1 {
    produto = $1
    qtd = $2
    receita = $2 * $3
    total_produto[produto] += qtd
    total_receita[produto] += receita
    receita_geral += receita
}
END {
    print "Produto | Qtd Total | Receita Total"
    print "-----------------------------------"
    for (p in total_produto) {
        printf "%-10s | %9d | %12.2f\n", p, total_produto[p], total_receita[p]
    }
    print "-----------------------------------"
    printf "TOTAL GERAL: R$ %.2f\n", receita_geral
}' vendas.csv | sort

Awk se consolida como uma ferramenta indispensável no ecossistema Shell para processamento de colunas e geração de relatórios. Sua sintaxe enxuta, combinada com poder de filtragem, formatação e agregação, permite resolver tarefas complexas de manipulação de dados com poucas linhas de código, seja em scripts inline ou arquivos dedicados.

Referências