grep, sed e awk: exemplos de processamento de texto no terminal Linux
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.
| Tarefa | Ferramenta | Exemplo |
|---|---|---|
| Encontrar linhas com um texto | grep | grep ERROR app.log |
| Substituir um texto | sed | sed 's/http:/https:/g' arquivo |
| Remover ou exibir linhas pelo número | sed | sed -n '10,20p' arquivo |
| Extrair uma coluna | awk | awk '{print $1}' access.log |
| Somar, calcular média ou agrupar | awk | awk '{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ção | Significado | Exemplo |
|---|---|---|
^ | início da linha | grep '^root' /etc/passwd |
$ | fim da linha | grep 'bash$' /etc/passwd |
. | qualquer caractere | grep 'h.t' |
* | 0 ou mais repetições | grep 'ab*c' |
+ (ERE) | 1 ou mais | grep -E '[0-9]+' |
| (ERE) | ou | grep -E 'error|warn' |
[...] | um caractere do conjunto | grep '[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$1por 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
gno sed. Sem ele, só a primeira correspondência da linha é trocada, e as demais permanecem. - Usar
sed -isem conferir. Uma expressão regular errada estraga o arquivo sem avisar. Teste antes sem-iou use-i.bak. +e|não funcionam no grep. É sintaxe estendida: usegrep -E(oused -E).- Ponto no padrão.
grep 192.168.1.1também encontra192x168y1z1, porque o ponto significa "qualquer caractere". Usegrep -Fou escape com\.. - Espaços dentro das colunas. Se um campo pode conter espaços (CSV, caminho), defina o separador explicitamente:
awk -F,ouawk -F'\t'. - cat desnecessário.
cat arquivo | grep xfunciona, masgrep 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.
Este tema é abordado em profundidade, com prática, no curso “Linux: с нуля до уверенного администрирования”.
Ir para o curso