Quem administra sistemas ou trabalha em cibersegurança passa boa parte do dia a olhar para texto estruturado: registos de acesso de um servidor web, o /etc/passwd, ficheiros CSV de inventário, saídas de comandos com colunas alinhadas. O awk nasceu precisamente para isso: lê a entrada registo a registo, parte cada registo em campos e aplica regras simples do tipo «se este padrão for verdadeiro, executa esta ação».
O resultado é uma ferramenta que, numa única linha de terminal, resolve tarefas que noutras linguagens exigiriam um script completo: extrair a coluna certa, filtrar por condição, somar valores, contar ocorrências e formatar um relatório. Neste artigo percorremos a estrutura do awk, as opções e variáveis que realmente interessam, e terminamos com um simulador interativo onde pode ver a decomposição em campos a acontecer, linha a linha.
O que faz o awk
O awk é, na verdade, uma pequena linguagem de programação orientada a registos. Um programa awk é uma lista de regras, cada uma com a forma padrão { ação }. Para cada registo lido (por omissão, cada linha), o awk avalia o padrão; se for verdadeiro, executa a ação. Antes disso, parte o registo em campos usando o separador definido em FS — por omissão, sequências de espaços e tabulações.
awk [opções] 'padrão { ação }' ficheiro...
Ambas as partes da regra são opcionais: sem padrão, a ação corre para todos os registos; sem ação, assume-se {print}, que imprime o registo inteiro. Em distribuições Linux, o comando awk costuma ser fornecido pelo gawk (GNU awk) ou pelo mawk, ambos compatíveis com o núcleo da linguagem definido no POSIX.
As opções que interessam
Campos e variáveis internas
$0— o registo completo;$1a$NF— os campos individuais, sendo$NFsempre o último, seja qual for o número de colunas.NF— número de campos do registo atual;NR— número do registo desde o início;FNR— número do registo dentro do ficheiro atual (útil com vários ficheiros).FSeOFS— separadores de campos de entrada e de saída;RSeORS— separadores de registos;FILENAME— nome do ficheiro em leitura.
awk '{print $1, $7}' access.log # IP e código de estado
awk '{print NR": "$0}' relatorio.txt # numera as linhas
Um pormenor que faz toda a diferença: no print, a vírgula entre argumentos insere o OFS (um espaço, por omissão); sem vírgula, o awk concatena os valores sem separador nenhum. print $1, $7 e print $1 $7 produzem resultados muito diferentes.
Padrões: regex, comparações e intervalos
O padrão pode ser uma expressão regular entre barras, aplicada a $0, ou qualquer condição sobre campos e variáveis. O operador ~ testa uma regex contra um campo específico (!~ nega), e &&, || e ! combinam condições. Um par padrão1, padrão2 define um intervalo: imprime desde o primeiro registo que casa com o primeiro padrão até ao que casa com o segundo.
awk '/403|500/ {print $1}' access.log # regex sobre $0
awk '$7 == 404 {print $6}' access.log # comparação num campo
awk -F':' '$3 >= 1000 {print $1}' /etc/passwd # condição numérica
awk 'NR==2, NR==4 {print}' dados.txt # intervalo de registos
BEGIN, END e acumuladores
O bloco BEGIN corre uma vez antes de ler o primeiro registo — ideal para imprimir cabeçalhos ou definir variáveis como o FS. O bloco END corre uma vez depois do último registo, quando NR já vale o total de registos lidos. Como as variáveis não precisam de ser declaradas e começam a zero (ou cadeia vazia), somar e contar torna-se trivial.
awk '{s += $10} END {print s}' access.log # soma de bytes transferidos
awk 'END {print NR}' access.log # equivalente a wc -l
Opções da linha de comandos
-F sep— define o separador de campos, por exemplo-F':'para o/etc/passwdou-F','para CSV simples. Aceita também uma expressão regular.-v var=valor— passa uma variável da shell para dentro do programa, de forma segura e sem truques de aspas.-f ficheiro.awk— lê o programa de um ficheiro, o formato certo quando a regra deixa de caber confortavelmente numa linha.
awk -F',' -v limite=100 '$3 > limite {print $2}' vendas.csv
Ações, funções e arrays associativos
Além do print, o printf dá controlo total sobre o formato (%s, %d, %8.2f, %-10s). As funções de texto incluem length(), substr(), index(), split(), sub()/gsub() para substituições com regex, e toupper()/tolower(). As instruções next e exit saltam para o registo seguinte ou terminam o programa. A joia da coroa são os arrays associativos, indexados por texto — a base do idioma clássico de contagem:
awk '{c[$1]++} END {for (ip in c) print c[ip], ip}' access.log
awk -F',' 'NR>1 {t[$1] += $3*$4} END {for (r in t) printf "%-8s %8.2f\n", r, t[r]}' vendas.csv
awk em cibersegurança
Em segurança, o awk é uma das ferramentas de triagem mais rápidas que existem, porque já está instalado em praticamente qualquer sistema:
- Análise de logs web: contar pedidos por IP (
{c[$1]++}), isolar códigos 4xx/5xx ou detetar tentativas de ataque como pedidos a/etc/passwdou a páginas de autenticação — o primeiro passo de qualquer investigação de incidente. - Auditoria de contas:
awk -F':' '$3 == 0 {print $1}' /etc/passwdrevela contas com UID 0 além do root;$7 ~ /bash/lista quem tem shell interativa — perguntas obrigatórias em hardening. - Deteção de exfiltração: somar bytes transferidos por origem (
{b[$1] += $10} END {...}) evidencia num instante o cliente que descarregou dados muito acima do normal. - Forense e relatórios: extrair e realinhar colunas de saídas de comandos de rede e processos, transformando texto em bruto em evidência legível para o relatório.
Experimente no simulador interativo
O simulador abaixo mostra o motor do awk por dentro: para cada registo, vê o $0, a decomposição em campos $1…$NF, os valores de NR, NF e FS, e se o padrão foi verdadeiro ou falso. Escolha um dos programas na grelha (de {print $1} a arrays associativos com END), use Anterior/Seguinte para navegar ou Demonstrar tudo para ver a sequência completa sobre três ficheiros de exemplo: um log de acessos, um passwd e um CSV de vendas.
Erros comuns e boas práticas
- Confundir
print $1, $7(comOFS) eprint $1 $7(concatenação sem separador) — o clássico de quem está a começar. - Esquecer as plicas à volta do programa: sem elas, a shell expande
$1antes de oawko ver. Use sempreawk '...'e passe valores externos com-v. - Tratar CSV real com
-F',': campos com vírgulas dentro de aspas quebram a divisão. Para CSV simples serve; para CSV complexo, use uma ferramenta com parser dedicado. - Contar colunas à mão quando
$NF(último campo) eNFresolvem o problema de forma robusta, mesmo com número de colunas variável. - Ignorar que variáveis não declaradas valem 0 ou cadeia vazia: é conveniente, mas também esconde erros de escrita no nome da variável.
- Usar extensões específicas do
gawk(comogensub()) em scripts que vão correr em sistemas commawkouawkPOSIX — teste a portabilidade antes de distribuir. - Saltar o cabeçalho de ficheiros tabulares com
NR > 1— pequeno hábito que evita somas e contagens contaminadas pela linha de títulos.
Conclusão
O awk condensa num só comando um ciclo de leitura, um parser de campos e uma linguagem de regras. Dominar meia dúzia de idiomas — {print $n}, padrões com regex e comparações, -F para mudar o separador, BEGIN/END e arrays associativos — chega para resolver a maioria das tarefas de análise de texto em administração de sistemas e segurança. Combine-o com o histórico da série, como a gestão de contas com o useradd, e o terminal passa a ser a sua primeira ferramenta de auditoria.
Se quer levar estas competências mais longe — da linha de comandos à resposta a incidentes — conheça os serviços de formação e consultoria em cibersegurança da HJFR no nosso catálogo de serviços.
Este artigo faz parte da série “Comandos Linux, um a um” do blog HJFR — fique atento aos próximos comandos.
