Fundamentos do sed: Substituição de Texto com o Editor de Fluxo
O Que Você Vai Aprender
- Os cinco padrões essenciais do sed (substituir / deletar / imprimir / endereço / multi-expressão) no caminho mais curto para fluência
- O padrão seguro para edições
-i(in-place) para parar de destruir arquivos - A diferença entre BRE e ERE (
-E) para que seu regex fique consistente comgrep -Eeawk
O padrão prático
- Sempre visualize na saída padrão primeiro, depois confirme com
-i.bak - O delimitador não precisa ser
/-- use|ou#ao reescrever caminhos - Esquecer a flag
gno final significa que apenas a primeira correspondência por linha será substituída
Premissas
- SO: Ubuntu / Debian / família RHEL Linux
- Versão do sed: GNU sed (BSD sed no macOS usa sintaxe diferente para
-i-- consulte a documentação do fornecedor)
O Que é o sed?
sed (editor de fluxo) lê a entrada linha por linha, aplica um script de edição e escreve na saída padrão. Diferente de editores interativos como o Vim, o sed foi feito para uso não interativo dentro de pipelines do shell -- normalização de logs, reescrita de configurações, preprocessamento de texto.
$ echo "hello world" | sed 's/world/Linux/' hello Linux
O comando s/old/new/ (substituição) representa aproximadamente 80% do uso real do sed.
Por Que Visualizar na Saída Padrão Primeiro?
sed -i sobrescreve o arquivo diretamente. Se você perceber depois que o padrão estava errado ou esqueceu de escapar uma /, a recuperação é difícil. Sempre visualize na saída padrão, depois confirme com -i.bak -- este é o único hábito confiável.
# 1. Visualizar na saida padrao $ sed 's/foo/bar/g' config.txt # 2. Confirmar com backup $ sed -i.bak 's/foo/bar/g' config.txt # 3. config.txt.bak e gerado automaticamente $ ls config.txt* config.txt config.txt.bak
Usar -i sem sufixo de backup é arriscado para trabalho em produção. Torne -i.bak um hábito -- reverter é apenas mv config.txt.bak config.txt.
1. Substituição: s/old/new/
1-1. Primeira correspondência em cada linha (padrão)
$ echo "apple apple apple" | sed 's/apple/orange/' orange apple apple
1-2. Todas as correspondências na linha (flag g)
$ echo "apple apple apple" | sed 's/apple/orange/g' orange orange orange
Esquecer o g é o erro #1 do sed. Se "apenas algumas correspondências mudaram," verifique primeiro se falta o g.
1-3. Sem diferenciar maiúsculas/minúsculas (flag I)
$ echo "Apple APPLE apple" | sed 's/apple/orange/gI' orange orange orange
A flag I é uma extensão do GNU sed. Evite-a em scripts portáveis (o sed POSIX não a suporta).
2. Mudando o Delimitador de /
Quando o padrão contém caminhos como /usr/local, escapar cada / rapidamente se torna ilegível. O caractere logo após s é o delimitador -- escolha |, # ou , para manter a legibilidade.
# Ruim: inferno de barras invertidas $ sed 's/\/usr\/local\/bin/\/opt\/bin/' file # Bom: pipe como delimitador $ sed 's|/usr/local/bin|/opt/bin|' file # Tambem bom: hash como delimitador $ sed 's#/usr/local/bin#/opt/bin#' file
Mudar o delimitador elimina 80% dos bugs de substituição. Para reescrita de caminhos, | ou # é o padrão de fato.
3. Endereços: Direcionando Linhas Específicas
Todo comando de edição do sed pode receber um prefixo de endereço que restringe em quais linhas ele é aplicado.
3-1. Por número de linha
$ sed '3s/foo/bar/' file # Apenas linha 3 $ sed '1,5s/foo/bar/g' file # Linhas 1-5 $ sed '10,$s/foo/bar/g' file # Linha 10 ate o final ($ = ultima linha)
3-2. Por padrão
# Apenas em linhas contendo "ERROR" $ sed '/ERROR/s/foo/bar/g' file # Entre /START/ e /END/ $ sed '/START/,/END/s/foo/bar/g' file
3-3. Negação (!)
# Todas as linhas exceto a linha 1 $ sed '1!s/foo/bar/g' file # Tudo exceto linhas de comentario (comecando com #) $ sed '/^#/!s/foo/bar/g' file
4. Deletar (d) e Imprimir (p)
4-1. Deletar linhas
$ sed '/^$/d' file # Deletar linhas vazias $ sed '/^#/d' file # Deletar linhas de comentario $ sed '1,5d' file # Deletar linhas 1-5 $ sed '$d' file # Deletar a ultima linha
4-2. Imprimir apenas linhas específicas (-n + p)
Por padrão, o sed imprime todas as linhas. A flag -n suprime a saída padrão, então você só vê as linhas que explicitamente imprimir com p.
# Imprimir linhas contendo "ERROR" (como grep "ERROR") $ sed -n '/ERROR/p' file # Imprimir linhas 10-20 $ sed -n '10,20p' file
sed -n 'Np' é mais rápido e claro que head -n N | tail -1 para extrair uma única linha.
5. Múltiplas Edições em Uma Passagem
5-1. Múltiplas expressões -e
$ sed -e 's/foo/bar/g' -e 's/hoge/fuga/g' file
5-2. Separadas por ponto e vírgula (GNU sed)
$ sed 's/foo/bar/g; s/hoge/fuga/g' file
5-3. Arquivo de script com -f
Salve conjuntos de transformações reutilizáveis em um arquivo.
$ cat replace.sed s/foo/bar/g s/hoge/fuga/g /^#/d $ sed -f replace.sed file
6. BRE vs ERE: Devo Sempre Usar -E?
O sed usa por padrão BRE (Expressões Regulares Básicas). Usar +, ?, | ou (...) requer escape com barra invertida, o que fica feio rapidamente. Adicionar -E muda para ERE (Expressões Regulares Estendidas) -- a mesma variante que grep -E e awk usam.
6-1. BRE (padrão)
# Grupos e quantificadores requerem \( \) e \{ \}
$ echo "2026-05-20" | sed 's/\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)/\3\/\2\/\1/'
20/05/20266-2. ERE (-E)
# Sem escape -- muito mais facil de ler
$ echo "2026-05-20" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
20/05/2026Torne -E seu padrão. O escape do BRE coloca carga cognitiva nos revisores e leva a bugs passando despercebidos.
6-3. Retro-referências (\1, \2, ...)
Grupos capturados são referenciados como \1, \2, etc. na substituição. Mesma sintaxe em BRE e ERE.
# "Sobrenome, Nome" -> "Nome Sobrenome" $ echo "Doe, John" | sed -E 's/(.+), (.+)/\2 \1/' John Doe
7. Armadilhas e Como Evitá-las
Top 5 armadilhas do sed
- Executar
-isem visualizar -- irrecuperável. Sempre visualize primeiro, depois use-i.bak - Flag
gausente -- apenas uma correspondência por linha é alterada - Esquecer de mudar o delimitador -- escape de
/torna padrões ilegveis - Misturar BRE e ERE -- escolha um e mantenha (
-Erecomendado) - Tratar
*ou.como literais -- são metacaracteres regex; escape-os
7-1. Escapando metacaracteres literais
# Ruim: . corresponde a qualquer caractere $ echo "192x168x0x1" | sed 's/192.168.0.1/X/' X # Bom: escape o ponto $ echo "192x168x0x1" | sed 's/192\.168\.0\.1/X/' 192x168x0x1
7-2. Incorporando variáveis do shell
Variáveis do shell não expandem dentro de aspas simples. Mude para aspas duplas -- mas cuidado com $ e \ dentro delas.
NEW="bar" # Ruim: $NEW e literal $ sed 's/foo/$NEW/g' file # Bom: aspas duplas para expansao $ sed "s/foo/$NEW/g" file
Se $NEW contiver /, & ou \, a substituição quebra. Mude o delimitador ou sanitize o valor antes de injetá-lo.
8. Receitas Práticas
Templates para copiar e colar
# Converter CRLF para LF
sed -i.bak 's/\r$//' file
# Remover linhas vazias e comentarios #
sed -e '/^$/d' -e '/^#/d' /etc/nginx/nginx.conf
# Mascarar enderecos IP
sed -E 's/\b([0-9]{1,3}\.){3}[0-9]{1,3}\b/x.x.x.x/g' access.log
# Remover espacos em branco no final
sed -i.bak 's/[[:space:]]*$//' file
# Inserir uma linha antes de linhas correspondentes a um padrao
sed -i.bak '/^pattern/i\
inserted line before' file
# Reescrever um valor YAML (apos chave:)
sed -i.bak -E 's/^(version:\s*).*/\1"1.2.3"/' config.yamlsed vs awk vs grep: Quando Usar Qual
| Tarefa | Melhor ferramenta |
|---|---|
| Substituição simples de strings | sed |
| Filtrar linhas correspondentes (grep-like) | grep / sed -n |
| Processamento por colunas (campos, soma) | awk |
| Transformações multi-linha | sed comando N ou awk |
| Dados estruturados (JSON / YAML) | jq / yq |
sed brilha em: edições de linha única em fluxo, baixo consumo de memória, disponível em todo Unix sed tem dificuldade com: dados colunares, formatos estruturados, lógica multi-linha -- mude para awk ou jq quando as coisas ficarem complexas