O awk é uma linguagem de programação e uma ferramenta de linha de comando amplamente utilizada no Linux para processamento e análise de texto. Seu nome vem das iniciais dos criadores: Alfred Aho, Peter Weinberger e Brian Kernighan. O awk é especialmente útil para trabalhar com dados estruturados em colunas, como arquivos CSV, logs e saídas de comandos. Diferente de ferramentas como grep ou sed, o awk oferece uma sintaxe mais próxima de uma linguagem de programação, com suporte a variáveis, condicionais e loops.

Nesta aula, vamos cobrir os conceitos fundamentais do awk: sua estrutura de padrão e ação, manipulação de campos, configuração de separadores e o comando print para exibir resultados. Esses tópicos formam a base para scripts mais avançados que você poderá desenvolver posteriormente.

Estrutura (padrão { ação })

O awk opera com um padrão básico: padrão { ação }. O programa awk lê linha por linha da entrada (arquivo ou stdin) e, para cada linha, verifica se o padrão é verdadeiro. Se for, executa a ação entre chaves. Se nenhum padrão for especificado, a ação é executada para todas as linhas.

Por exemplo, o comando awk '{ print }' arquivo.txt simplesmente imprime cada linha do arquivo, pois não há padrão. Já awk '/erro/ { print }' log.txt imprime apenas as linhas que contêm a palavra "erro". O padrão pode ser uma expressão regular (entre barras), uma condição numérica ou lógica, ou até mesmo uma combinação delas. A ação pode conter múltiplos comandos separados por ponto e vírgula ou quebras de linha.

# Exemplo básico: imprimir linhas que contenham "warning"
awk '/warning/ { print }' /var/log/syslog

# Exemplo com padrão numérico: linhas onde o primeiro campo é maior que 100
awk '$1 > 100 { print $1, $2 }' dados.txt

Campos ($1, $2)

No awk, cada linha é automaticamente dividida em campos, que são acessados por $1, $2, $3, etc., sendo $0 a linha inteira. Por padrão, os campos são separados por espaços em branco (espaços ou tabulações). Isso torna o awk ideal para processar saídas de comandos como ls -l ou ps aux.

Por exemplo, para listar apenas os nomes de arquivos de um diretório (ignorando permissões, tamanhos etc.), podemos usar ls -l | awk '{ print $9 }' (o nono campo é o nome do arquivo). É importante notar que a contagem de campos começa em 1. Se o número de campos variar por linha, campos inexistentes são tratados como string vazia.

# Exemplo: extrair PID e comando de 'ps aux'
ps aux | awk '{ print $2, $11 }'

# Exemplo: somar o tamanho de todos os arquivos (coluna 5) de 'ls -l'
ls -l | awk '{ total += $5 } END { print "Total: " total " bytes" }'

Separadores

O separador de campos padrão no awk é qualquer sequência de espaços ou tabulações. No entanto, podemos alterá-lo usando a opção -F (ou a variável FS dentro do script). Isso é útil quando os dados são separados por vírgulas (CSV), dois-pontos (/etc/passwd) ou outros caracteres.

Por exemplo, para processar o arquivo /etc/passwd, que usa dois-pontos como separador, usamos awk -F: '{ print $1 }' /etc/passwd para obter os nomes de usuário. O separador pode ser uma expressão regular, como -F'[,\t]' para vírgula ou tabulação.

# Exemplo: extrair nome e UID do /etc/passwd
awk -F: '{ print $1, $3 }' /etc/passwd

# Exemplo: arquivo CSV, imprimir colunas 1 e 3
awk -F, '{ print $1, $3 }' dados.csv

print

O comando print é a principal forma de exibir saída no awk. Ele imprime os argumentos separados por um espaço (ou pelo separador de saída OFS). Se nenhum argumento for fornecido, imprime $0 (a linha inteira). Podemos usar print para formatar a saída, combinando campos, strings e variáveis.

Além do print, existe o printf para formatação mais controlada (similar ao C). Por exemplo, printf "%s\t%d\n", $1, $2 imprime o primeiro campo como string e o segundo como inteiro, separados por tabulação. O print simples adiciona uma nova linha ao final automaticamente.

# Exemplo: imprimir campos com texto explicativo
awk '{ print "Nome: " $1, "Idade: " $2 }' pessoas.txt

# Exemplo: usar print sem argumentos para imprimir a linha inteira
awk '/importante/ { print }' notas.txt

# Exemplo: formatar com printf (largura fixa)
awk '{ printf "%-10s %5d\n", $1, $2 }' dados.txt

Boas práticas

Ao usar awk, é recomendável sempre testar o comando em um pequeno conjunto de dados antes de aplicá-lo a arquivos grandes. Use head para ver as primeiras linhas. Lembre-se de que o awk é sensível a maiúsculas/minúsculas e espaços. Para scripts mais complexos, considere salvar o programa awk em um arquivo separado e usar awk -f script.awk dados.txt. Além disso, familiarize-se com variáveis internas como NR (número da linha) e NF (número de campos na linha atual).

Exercícios

  1. Crie um comando awk que imprima apenas a primeira coluna de um arquivo chamado notas.txt (separado por espaços).

    ✓ Resposta:
    awk '{ print $1 }' notas.txt
  2. Usando o arquivo /etc/passwd (separado por dois-pontos), escreva um comando awk que exiba o nome de usuário e o diretório home (colunas 1 e 6).

    ✓ Resposta:
    awk -F: '{ print $1, $6 }' /etc/passwd
  3. Escreva um comando awk que imprima linhas de dados.txt onde o segundo campo é maior que 50.

    ✓ Resposta:
    awk '$2 > 50 { print }' dados.txt
  4. Dado um arquivo CSV vendas.csv com colunas: produto, quantidade, preço. Use awk para calcular o valor total (quantidade * preço) de cada linha e exibir produto e total.

    ✓ Resposta:
    awk -F, '{ total = $2 * $3; print $1, total }' vendas.csv
  5. Use awk para imprimir as linhas 10 a 20 de um arquivo log.txt. Dica: use a variável NR.

    ✓ Resposta:
    awk 'NR >= 10 && NR <= 20 { print }' log.txt

Referências