O awk é uma ferramenta de processamento de texto e extração de dados presente em praticamente todas as distribuições Linux. Diferente de ferramentas como grep (que filtra linhas) e sed (que edita linhas), o awk trata cada linha como um registro composto por campos, permitindo operações baseadas em padrões e ações sobre esses campos. É ideal para gerar relatórios, transformar dados tabulares e automatizar análises de logs.

Nesta aula, vamos nos concentrar nos conceitos fundamentais: a estrutura de um programa awk (padrão { ação }), como acessar campos individuais ($1, $2), como controlar o separador de campos (FS) e como usar o comando print para exibir resultados.

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

Um programa awk é composto por uma série de regras no formato padrão { ação }. O padrão é uma condição que, quando verdadeira para uma linha de entrada, faz com que a ação associada seja executada. Se o padrão for omitido, a ação é executada para todas as linhas. Se a ação for omitida, o padrão é usado como condição e a linha é impressa (equivalente a { print }).

Por exemplo, o comando a seguir imprime todas as linhas do arquivo dados.txt (ação print sem padrão):

awk '{ print }' dados.txt

Já o exemplo abaixo imprime apenas as linhas que contêm a palavra "erro":

awk '/erro/ { print }' dados.txt

O padrão pode ser uma expressão regular (entre barras), uma expressão relacional (como $1 > 100), ou uma combinação lógica. A ação pode conter múltiplos comandos separados por ponto e vírgula ou por quebras de linha entre chaves.

Campos ($1, $2)

O awk divide cada linha de entrada em campos baseados em um separador (por padrão, espaços em branco consecutivos ou tabulações). O primeiro campo é acessado por $1, o segundo por $2, e assim por diante. $0 representa a linha inteira.

Considere o arquivo alunos.txt com o seguinte conteúdo:

João 85
Maria 92
Pedro 78

Para imprimir apenas os nomes (primeiro campo):

awk '{ print $1 }' alunos.txt

Saída:

João
Maria
Pedro

Para imprimir nome e nota separados por hífen:

awk '{ print $1 " - " $2 }' alunos.txt

Saída:

João - 85
Maria - 92
Pedro - 78

Campos numéricos podem ser usados em operações aritméticas. Por exemplo, para calcular a média das notas:

awk '{ soma += $2 } END { print "Média: " soma/NR }' alunos.txt

O bloco END é executado após o processamento de todas as linhas. NR é uma variável interna que contém o número de registros (linhas) processados.

Separadores

O separador de campos padrão do awk é qualquer sequência de espaços e/ou tabulações. Para alterá-lo, usamos a opção -F ou a variável interna FS (Field Separator).

Suponha um arquivo dados.csv com campos separados por vírgula:

nome,idade,cidade
Ana,30,São Paulo
Carlos,25,Rio de Janeiro

Para imprimir o nome e a cidade:

awk -F ',' '{ print $1, $3 }' dados.csv

Ou equivalentemente, usando BEGIN para definir FS:

awk 'BEGIN { FS = "," } { print $1, $3 }' dados.csv

O bloco BEGIN é executado antes de ler a primeira linha. Também podemos usar expressões regulares como separador. Por exemplo, para separar por um ou mais dois-pontos:

awk -F ':+' '{ print $1 }' arquivo.txt

Além do FS, existe a variável OFS (Output Field Separator) que define o separador usado na saída do print (padrão é espaço). Para imprimir campos separados por vírgula:

awk 'BEGIN { OFS = "," } { print $1, $2 }' alunos.txt

Saída:

João,85
Maria,92
Pedro,78

print

O comando print é a principal forma de gerar saída no awk. Ele imprime seus argumentos separados pelo valor de OFS (padrão espaço) e termina com um caractere de nova linha (controlado por ORS, Output Record Separator).

Podemos imprimir strings literais, variáveis, campos e expressões. Exemplos:

# Imprime a linha inteira
awk '{ print $0 }' arquivo

# Imprime dois campos com um espaço entre eles (padrão)
awk '{ print $1, $2 }' arquivo

# Imprime com texto explicativo
awk '{ print "Nome: " $1 ", Nota: " $2 }' arquivo

# Imprime sem nova linha no final (usando printf)
awk '{ printf "%s\t%s\n", $1, $2 }' arquivo

O printf permite formatação mais controlada, similar à linguagem C. Por exemplo, para alinhar colunas:

awk '{ printf "%-10s %5d\n", $1, $2 }' alunos.txt

Saída:

João          85
Maria         92
Pedro         78

Note que print adiciona automaticamente uma nova linha; printf não. Use \n para quebra de linha em printf.

Referências

Exercícios

  1. Crie um arquivo chamado notas.txt com o seguinte conteúdo (separado por espaços):
    Ana 7.5 8.0 9.0
    Carlos 6.0 7.5 8.5
    Bruna 9.0 9.5 10.0
    Escreva um comando awk que imprima o nome e a média aritmética das três notas (com duas casas decimais).

    ✓ Resposta:
    awk '{ media = ($2+$3+$4)/3; printf "%s %.2f\n", $1, media }' notas.txt
  2. Dado o arquivo pessoas.csv com campos separados por ponto e vírgula:
    João;35;Programador
    Maria;28;Designer
    Pedro;42;Gerente
    Use awk para imprimir apenas o nome e a profissão, separados por " - ".

    ✓ Resposta:
    awk -F ';' '{ print $1 " - " $3 }' pessoas.csv
  3. Explique a diferença entre print $1, $2 e print $1 $2 no awk.

    ✓ Resposta: print $1, $2 imprime os campos separados pelo separador de saída (OFS, padrão espaço). Já print $1 $2 concatena os campos sem separador (a vírgula é omitida, então os campos são concatenados como strings). Por exemplo, se $1="João" e $2="85", o primeiro imprime "João 85" e o segundo imprime "João85".
  4. Escreva um comando awk que leia o arquivo dados.txt e imprima apenas as linhas cujo segundo campo seja maior que 50 (suponha que o segundo campo seja numérico).

    ✓ Resposta:
    awk '$2 > 50' dados.txt

    Ou explicitamente: awk '$2 > 50 { print }' dados.txt

  5. Usando o arquivo alunos.txt do exemplo (João 85, Maria 92, Pedro 78), crie um comando awk que imprima o nome e a nota, mas com a nota formatada com 3 dígitos (ex: 085, 092, 078). Dica: use printf com formato %03d.

    ✓ Resposta:
    awk '{ printf "%s %03d\n", $1, $2 }' alunos.txt