Tutorial

grep, sed e awk: exemplos de processamento de texto no terminal Linux

Atualizado: · Skillaria.Top

O grep encontra linhas por padrão (grep -rn error /var/log), o sed altera texto no fluxo ou no arquivo (sed -i 's/antigo/novo/g' arquivo) e o awk trabalha com colunas e faz contagens (awk '{print $1}' access.log). Juntos, em um pipeline, substituem um script: o grep filtra linhas, o sed corrige o texto e o awk recorta campos e agrega dados.

grep, sed e awk são três utilitários clássicos do Linux para processar texto. O grep encontra linhas que combinam com um padrão, o sed substitui e remove trechos do texto sem abrir um editor, e o awk separa cada linha em colunas e sabe fazer contas. A seguir estão exemplos de grep, sed e awk que você realmente usa ao analisar logs, arquivos de configuração e a saída de comandos, além dos erros mais comuns.

Quando usar cada um

As três ferramentas leem o texto linha por linha e escrevem o resultado na saída padrão, por isso é fácil encadeá-las com |. A diferença está na tarefa que cada uma resolve melhor.

TarefaFerramentaExemplo
Encontrar linhas com um textogrepgrep ERROR app.log
Substituir um textosedsed 's/http:/https:/g' arquivo
Remover ou exibir linhas pelo númerosedsed -n '10,20p' arquivo
Extrair uma colunaawkawk '{print $1}' access.log
Somar, calcular média ou agruparawkawk '{s+=$10} END {print s}'

Regra simples: se você só precisa filtrar, use grep; se precisa alterar o texto, use sed; se o texto tem colunas ou você precisa de aritmética, use awk.

grep: buscar linhas por padrão

Exemplos básicos de grep

# Linhas com a palavra error no arquivo
grep error /var/log/syslog

# Sem diferenciar maiúsculas e minúsculas: Error, ERROR, error
grep -i error app.log

# Com números de linha
grep -n "Connection refused" app.log

# Recursivamente em um diretório, com nomes de arquivo
grep -rn "DB_HOST" /etc/myapp/

# Apenas os nomes dos arquivos onde há correspondência
grep -rl "TODO" src/

# Inverter: tudo, EXCETO comentários e linhas vazias
grep -v -e '^#' -e '^$' /etc/ssh/sshd_config

# Contar o número de linhas encontradas
grep -c " 500 " access.log

A opção -w busca a palavra inteira: grep -w log não encontra login. A opção -F desativa as expressões regulares e busca a string literalmente, o que é útil quando o padrão tem pontos, parênteses ou asteriscos.

Contexto ao redor da linha encontrada

Um erro no log raramente se entende por uma única linha; é preciso ver a pilha ou a requisição que levou até ele. Para isso existem as opções de contexto:

# 3 linhas depois da correspondência (After)
grep -A 3 "Traceback" app.log

# 2 linhas antes (Before)
grep -B 2 "OOM" /var/log/kern.log

# 5 linhas de cada lado (Context)
grep -C 5 "segfault" /var/log/syslog

O grep separa os grupos de correspondências com uma linha --, então a saída fica fácil de ler.

grep e expressões regulares

Por padrão, o grep entende expressões regulares básicas (BRE). Com a opção -E ativam-se as estendidas (ERE), nas quais +, ?, | e parênteses funcionam sem barras invertidas.

ConstruçãoSignificadoExemplo
^início da linhagrep '^root' /etc/passwd
$fim da linhagrep 'bash$' /etc/passwd
.qualquer caracteregrep 'h.t'
*0 ou mais repetiçõesgrep 'ab*c'
+ (ERE)1 ou maisgrep -E '[0-9]+'
| (ERE)ougrep -E 'error|warn'
[...]um caractere do conjuntogrep '[Ee]rror'
# Linhas com erros ou avisos
grep -E "ERROR|WARN" app.log

# Apenas endereços IP do log, um por linha (-o imprime somente a correspondência)
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' access.log

grep -P: extrair um valor entre trechos conhecidos

O GNU grep tem a opção -P, que usa expressões regulares no estilo Perl. Com ela você tem \K ("descartar tudo o que foi casado até aqui") e lookahead, o que permite extrair apenas o valor:

$ echo 'user_id=4821 status=ok' | grep -oP 'user_id=\K[0-9]+'
4821

$ grep -oP '"version":\s*"\K[^"]+' package.json
2.4.1

A opção -P não existe em todas as versões do grep (por exemplo, o grep BSD do macOS não a tem), então em scripts portáveis é melhor usar sed ou awk.

grep -q em condições de scripts

grep -q não imprime nada e apenas retorna o código de saída: 0 se encontrou, 1 se não encontrou. Assim, a verificação cabe direto no if:

if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
  echo "login do root desativado"
fi

É mais curto do que guardar a saída em uma variável e testar se ela está vazia, e o grep para na primeira correspondência.

sed: substituir e remover texto

Substituição: o comando s

O comando principal do sed é s/padrão/substituição/opções. Sem a opção g, apenas a primeira correspondência em cada linha é trocada.

# Mostrar o texto com a substituição (o arquivo não muda)
sed 's/foo/bar/' arquivo.txt

# Substituir todas as ocorrências da linha
sed 's/foo/bar/g' arquivo.txt

# Sem diferenciar maiúsculas e minúsculas (GNU sed)
sed 's/error/ERROR/gI' app.log

# Outro delimitador, se o texto tiver barras
sed 's|/var/www|/srv/www|g' nginx.conf

sed -i: substituir diretamente no arquivo

A opção -i grava o resultado de volta no arquivo. Para não perder o original, defina um sufixo de cópia de segurança:

# Cria config.ini.bak e altera config.ini
sed -i.bak 's/^debug=true/debug=false/' config.ini

# Substituição em todos os .conf de um diretório
find /etc/myapp -name "*.conf" -exec sed -i 's/old-host/new-host/g' {} +

Antes de uma edição em massa, execute o comando sem -i e veja a saída. No macOS (sed BSD), o -i exige um argumento: sed -i '' 's/a/b/' arquivo.

Trabalhar com linhas pelo número e pelo padrão

# Mostrar as linhas 10 a 20 (-n desativa a impressão automática, p imprime)
sed -n '10,20p' arquivo.txt

# Remover a linha 5
sed '5d' arquivo.txt

# Remover a última linha
sed '$d' arquivo.txt

# Remover linhas vazias e comentários
sed -e '/^$/d' -e '/^#/d' nginx.conf

# Substituir apenas nas linhas que contêm "listen"
sed '/listen/s/80/8080/' nginx.conf

# Inserir uma linha depois da correspondência (GNU sed)
sed '/^\[mysqld\]/a max_connections = 500' my.cnf

Referências retroativas e &

Um trecho do padrão entre parênteses pode ser reutilizado na substituição com \1, \2, e o caractere & representa todo o texto encontrado.

# Trocar nome e sobrenome de lugar (ERE com -E)
$ echo "Silva João" | sed -E 's/(\S+) (\S+)/\2 \1/'
João Silva

# Colocar todos os números entre colchetes
$ echo "port 8080, timeout 30" | sed -E 's/[0-9]+/[&]/g'
port [8080], timeout [30]

# Transformar a data 2026-10-14 em 14.10.2026
$ echo 2026-10-14 | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/'
14.10.2026

awk: colunas, condições e contagens

Imprimir a coluna desejada

O awk divide cada linha em campos pelos espaços e tabulações: $1 é o primeiro campo, $2 o segundo, $NF o último, e $0 a linha inteira.

# Endereços IP do log do nginx (primeira coluna)
awk '{print $1}' /var/log/nginx/access.log

# Nome de usuário e shell de /etc/passwd (separador: dois-pontos)
awk -F: '{print $1, $7}' /etc/passwd

# Última coluna
df -h | awk '{print $NF}'

# Separador próprio na saída
awk -F: -v OFS=';' '{print $1, $3}' /etc/passwd

Condições: imprimir só as linhas necessárias

Antes do bloco entre chaves você pode colocar uma condição: o awk executa a ação apenas nas linhas que a satisfazem.

# Usuários com UID 1000 ou maior (usuários comuns, não de sistema)
awk -F: '$3 >= 1000 {print $1}' /etc/passwd

# Requisições com código de resposta 500 ou superior (9º campo no formato combined)
awk '$9 >= 500' access.log

# Linhas em que a 6ª coluna combina com a expressão regular
awk '$6 ~ /POST/' access.log

# Arquivos maiores que 100 MB na saída do ls -l
ls -l | awk '$5 > 100*1024*1024 {print $9}'

BEGIN, END e NR: awk como um pequeno programa

O bloco BEGIN é executado antes de ler a primeira linha, e o END, depois da última. NR guarda o número da linha atual, e no bloco END, o total de linhas.

# Soma dos tamanhos das respostas (10º campo) em megabytes
awk '{sum += $10} END {printf "%.1f MB\n", sum/1024/1024}' access.log

# Tempo médio de resposta a partir da última coluna
awk '{s += $NF} END {if (NR) print s/NR}' timings.log

# Pular o cabeçalho de um CSV
awk -F, 'NR > 1 {print $2}' users.csv

# Contagem de requisições por IP: array associativo
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head

O último exemplo é um clássico da análise de logs: o array count, com o IP como chave, substitui o encadeamento sort | uniq -c e se estende facilmente, por exemplo, para somar o tráfego de cada endereço.

Pipelines: grep, sed e awk juntos

A força está na combinação. Cada ferramenta faz a sua parte, e o | passa o resultado adiante.

Top 10 IPs com erros 5xx

grep ' 50[0-9] ' /var/log/nginx/access.log \
  | awk '{print $1}' \
  | sort | uniq -c | sort -rn | head -10
    412 203.0.113.45
    118 198.51.100.7
     36 192.0.2.19

Aqui o grep faz uma filtragem grosseira das linhas, o awk recorta o campo, e o sort | uniq -c conta as repetições. Dá para fazer tudo em um único awk: awk '$9 ~ /^5/ {c[$1]++} END {for (i in c) print c[i], i}' access.log | sort -rn | head. Essa versão é mais precisa, porque verifica exatamente a coluna do código de resposta.

Quais URLs são acessadas com mais frequência

awk '{print $7}' access.log | sed 's/?.*//' | sort | uniq -c | sort -rn | head

O sed corta a parte da query string, para que /search?q=a e /search?q=b sejam contados como uma mesma página.

Valores de uma configuração, sem comentários

grep -v '^\s*#' /etc/myapp/app.env | grep '=' | awk -F= '{print $1}'

Erros de uma hora específica

grep '14/Oct/2026:03:' access.log | awk '$9 >= 500 {print $4, $7, $9}'

Erros comuns

  • Aspas duplas em vez de simples no awk. Em awk "{print $1}", o shell substitui $1 por sua própria variável antes de o awk ser executado. Escreva o programa do awk e as expressões do sed entre aspas simples.
  • Esquecer o g no sed. Sem ele, só a primeira correspondência da linha é trocada, e as demais permanecem.
  • Usar sed -i sem conferir. Uma expressão regular errada estraga o arquivo sem avisar. Teste antes sem -i ou use -i.bak.
  • + e | não funcionam no grep. É sintaxe estendida: use grep -E (ou sed -E).
  • Ponto no padrão. grep 192.168.1.1 também encontra 192x168y1z1, porque o ponto significa "qualquer caractere". Use grep -F ou escape com \..
  • Espaços dentro das colunas. Se um campo pode conter espaços (CSV, caminho), defina o separador explicitamente: awk -F, ou awk -F'\t'.
  • cat desnecessário. cat arquivo | grep x funciona, mas grep x arquivo é mais curto e não cria um processo a mais.

Alternativas ao grep, sed e awk

Para JSON, essas ferramentas são incômodas: a estrutura é melhor tratada com jq (jq '.items[] | select(.status=="active") | .name'), e YAML, com yq. Para buscas recursivas rápidas em projetos grandes, é comum usar o ripgrep (comando rg), que por padrão respeita o .gitignore. Se você prefere a sintaxe do Perl, perl -pe 's/a/b/g' e perl -lane 'print $F[0]' substituem sed e awk em uma linha. Mas grep, sed e awk estão presentes em praticamente qualquer servidor, sem instalação, por isso vale aprendê-los primeiro.

Resumo

grep busca linhas, sed as altera, e awk trabalha com colunas e faz contas. Guarde o conjunto básico: grep -rniE com -A/-B/-C, sed 's/.../.../g' com -i.bak e -n 'Np', e awk -F com $1, $NF, condições e o bloco END. Com essas peças você monta quase qualquer análise de logs. Estes exemplos de grep, sed e awk, junto com find, jq e curl, são praticados na aula do curso de Linux sobre processamento de texto no terminal.

Perguntas frequentes

Qual é a diferença entre grep e egrep?

egrep é um apelido antigo para grep -E (expressões regulares estendidas). As versões atuais do GNU grep exibem um aviso ao chamar egrep, então use grep -E.

Como encontrar um texto em todos os arquivos de um diretório no Linux?

Use grep -rn "texto" /caminho: -r busca recursivamente e -n mostra o número da linha. Para limitar os tipos de arquivo, acrescente --include="*.php".

Como substituir um texto em vários arquivos de uma vez?

Combine a busca com o sed: grep -rl "antigo" . | xargs sed -i 's/antigo/novo/g'. Antes disso, convém fazer um commit ou uma cópia de segurança.

Como mostrar várias colunas separadas por tabulação no awk?

Defina o separador de saída: awk -v OFS='\t' '{print $1, $3}' arquivo. Sem o OFS, os campos impressos com vírgula são separados por espaço.

Como remover espaços no fim das linhas com sed?

O comando sed -i 's/[[:space:]]*$//' arquivo remove espaços e tabulações no fim de todas as linhas do arquivo.

Aprenda este tema em vídeo

Este tema é abordado em profundidade, com prática, no curso “Linux: с нуля до уверенного администрирования”.

Ir para o curso