Sed: transformando texto em stream

1. Introdução ao Sed

Sed (Stream Editor) é uma ferramenta poderosa do Unix/Linux projetada para processar texto de forma não interativa, linha a linha. Diferente de editores como Vim ou Nano, o Sed recebe um fluxo de dados (stdin ou arquivo), aplica transformações programadas e envia o resultado para a saída padrão (stdout).

A filosofia do Sed é simples: leia uma linha, armazene no espaço de padrão, aplique os comandos especificados e produza a saída. Esse ciclo se repete até o fim do arquivo. Essa abordagem em stream permite processar arquivos enormes sem carregá-los inteiramente na memória.

Ao contrário do Awk, que é mais orientado a campos e possui uma linguagem de programação completa, o Sed é focado em edições baseadas em linhas e expressões regulares. Já o Grep é apenas para busca e filtragem, sem capacidade de transformação. O Sed ocupa um nicho específico: edição programática e eficiente de texto.

2. Estrutura básica e sintaxe

A sintaxe geral do Sed é:

sed [opções] 'comando' arquivo

O comando pode incluir endereçamento, que define a quais linhas aplicar a ação. Os modos de endereçamento incluem:

  • Linhas específicas: 5 (apenas linha 5)
  • Intervalos: 3,7 (linhas 3 a 7)
  • Expressões regulares: /padrão/ (linhas que contêm o padrão)
  • Combinados: /início/,/fim/ (intervalo entre dois padrões)

Opções comuns:

  • -n: modo silencioso, não imprime linhas automaticamente
  • -i: edição in-place, altera o arquivo diretamente
  • -e: permite múltiplos comandos

Exemplo básico:

sed 's/erro/ERRO/' log.txt

Substitui a primeira ocorrência de "erro" por "ERRO" em cada linha do arquivo.

3. Comandos de substituição

O comando s é o mais utilizado. Sua estrutura é:

sed 's/padrão/substituto/modificadores'

Modificadores importantes:

  • g: substitui todas as ocorrências na linha (global)
  • p: imprime a linha após a substituição (usado com -n)
  • i: ignora diferenças entre maiúsculas e minúsculas (case-insensitive)

Exemplos práticos:

# Substituir todas as ocorrências de "foo" por "bar"
sed 's/foo/bar/g' arquivo.txt

# Substituir apenas na linha 10
sed '10s/foo/bar/' arquivo.txt

# Substituir ignorando case
sed 's/foo/bar/gi' arquivo.txt

Grupos de captura com \( e \) permitem referenciar partes do padrão com \1, \2, etc.:

# Inverter nome e sobrenome
echo "João Silva" | sed 's/\([A-Za-z]*\) \([A-Za-z]*\)/\2, \1/'

Saída: Silva, João

4. Comandos de exclusão e impressão

O comando d deleta linhas inteiras:

# Deletar linhas 5 a 10
sed '5,10d' arquivo.txt

# Deletar linhas que contêm "DEBUG"
sed '/DEBUG/d' log.txt

O comando p imprime linhas explicitamente, geralmente combinado com -n:

# Imprimir apenas linhas 3 a 6
sed -n '3,6p' arquivo.txt

# Imprimir linhas que contêm "ERROR"
sed -n '/ERROR/p' log.txt

A inversão com ! aplica o comando ao complemento do endereço:

# Imprimir tudo exceto as linhas 1-5
sed -n '1,5!p' arquivo.txt

# Deletar tudo exceto linhas com "IMPORTANTE"
sed '/IMPORTANTE/!d' notas.txt

5. Comandos de inserção, anexação e alteração

Estes comandos trabalham com linhas completas:

  • i: insere texto antes da linha endereçada
  • a: anexa texto após a linha endereçada
  • c: substitui a linha endereçada pelo texto

Exemplos:

# Inserir cabeçalho antes da linha 1
sed '1i\# Arquivo de Configuração' config.txt

# Anexar rodapé após a última linha
sed '$a\# Fim do arquivo' config.txt

# Substituir linhas com "TODO" por marcador
sed '/TODO/c\# PENDENTE - revisar' tasks.txt

Para múltiplas linhas de inserção, use \n ou múltiplos comandos:

sed '1i\Linha 1\'
sed '1i\Linha 2' arquivo.txt

6. Uso de múltiplos comandos e scripts

Para aplicar vários comandos, use -e ou ponto e vírgula:

# Com -e
sed -e 's/foo/bar/' -e 's/baz/qux/' arquivo.txt

# Com ponto e vírgula
sed 's/foo/bar/; s/baz/qux/' arquivo.txt

Blocos de comandos com chaves { } permitem aplicar múltiplas ações a um mesmo endereço:

# Nas linhas 10-20, substituir e deletar
sed '10,20{
    s/erro/ERRO/g
    /CRÍTICO/d
}' log.txt

Para scripts Sed externos, use -f:

# Conteúdo de script.sed:
s/foo/bar/g
/^#/d

# Execução:
sed -f script.sed arquivo.txt

7. Técnicas avançadas com Sed

O Sed possui dois buffers: espaço de padrão (onde a linha atual é processada) e espaço de retenção (armazenamento auxiliar). Comandos para manipulá-los:

  • h: copia espaço de padrão para espaço de retenção
  • H: anexa ao espaço de retenção
  • g: copia espaço de retenção para espaço de padrão
  • G: anexa ao espaço de padrão
  • x: troca os dois espaços

Exemplo prático: inverter ordem das linhas de um arquivo:

sed -n '1!G;h;$p' arquivo.txt

Laços e branching com :label, b (branch incondicional) e t (branch se houve substituição):

# Juntar linhas que não terminam com ponto final
sed ':a; /\.$/!{N; s/\n/ /; ba}' texto.txt

Processamento de múltiplas linhas com N, D, P:

  • N: adiciona próxima linha ao espaço de padrão
  • D: deleta até o primeiro \n no espaço de padrão
  • P: imprime até o primeiro \n

Exemplo: substituir quebras de linha entre parênteses:

sed '/^(/{:a; /)$/!{N; ba}; s/\n//g}' arquivo.txt

8. Exemplos práticos e boas práticas

Substituições em arquivos de configuração:

# Alterar porta em arquivo de configuração
sed -i 's/^port=.*/port=8080/' server.conf

# Comentar linhas com "debug=true"
sed -i '/^debug=true/s/^/#/' app.properties

Filtragem e transformação de logs:

# Extrair apenas timestamps e níveis de log
sed -n 's/^\([0-9:-]*\) \[\([A-Z]*\)\].*/\1 \2/p' app.log

# Remover linhas de debug e info
sed '/\[DEBUG\]\|\[INFO\]/d' system.log

Boas práticas:

  • Sempre faça backup antes de usar -i: sed -i.bak 's/foo/bar/' arquivo
  • Escape caracteres especiais no padrão: s/\./\./g para ponto literal
  • Use aspas simples para evitar expansão de variáveis pelo shell
  • Para arquivos grandes, evite -i e use redirecionamento: sed 'comando' grande.txt > novo.txt
  • Cuidado com encoding: Sed opera em bytes, não caracteres Unicode completos
  • Teste com -n e p antes de aplicar alterações destrutivas

Referências