sed avançado
Nesta aula, você aprenderá técnicas avançadas de sed, incluindo deleção e inserção de linhas, uso de grupos de captura e backreferences, edição in-place com a opção -i, e exemplos práticos que combinam esses recursos para manipular textos de forma eficiente.
O sed (Stream Editor) é uma ferramenta poderosa para processamento de texto em scripts de shell. Nesta aula, vamos explorar recursos avançados que vão além da substituição básica de padrões. Você aprenderá a deletar e inserir linhas com precisão, a usar grupos de captura e backreferences para reestruturar textos, e a editar arquivos diretamente com a opção -i. Esses recursos são essenciais para automatizar tarefas de manipulação de arquivos de configuração, logs e dados estruturados.
Dominar o sed avançado permite que você realize transformações complexas em uma única linha de comando, evitando a necessidade de escrever scripts longos em outras linguagens. Vamos começar com os conceitos de deleção e inserção, que são fundamentais para editar arquivos de forma programática.
Deleção e inserção
O sed permite deletar linhas que correspondem a um padrão ou que estão em um intervalo específico. O comando de deleção é d. Por exemplo, para deletar todas as linhas que contêm a palavra "erro" de um arquivo, usamos:
sed '/erro/d' arquivo.log
Você também pode deletar por número de linha ou intervalos. Por exemplo, sed '1,5d' arquivo deleta as cinco primeiras linhas. Para deletar linhas que correspondem a dois padrões diferentes, use sed '/padrão1/,/padrão2/d', que deleta desde a primeira linha que corresponde a padrão1 até a primeira linha que corresponde a padrão2 (inclusive).
A inserção de linhas é feita com os comandos i (insert) e a (append). O comando i insere uma linha antes da linha que corresponde ao padrão, enquanto a insere depois. Por exemplo, para inserir uma linha "INÍCIO" antes de cada linha que contém "dados", usamos:
sed '/dados/i INÍCIO' arquivo.txt
Para inserir múltiplas linhas, você pode usar
dentro do texto, ou usar um script com várias linhas. Por exemplo:
sed '/dados/i Linha1\nLinha2' arquivo.txt
Esses comandos são úteis para adicionar cabeçalhos, rodapés ou separadores em arquivos de texto.
Grupos e backreferences
O sed suporta expressões regulares com grupos de captura, que permitem reutilizar partes do texto que correspondem ao padrão. Os grupos são definidos com parênteses \( e \) (no sed básico) ou ( e ) se você usar a opção -E (extended regex). As backreferences são referências a esses grupos, usando \1, \2, etc.
Um exemplo clássico: inverter a ordem de nome e sobrenome em uma lista. Suponha que temos linhas no formato "Sobrenome, Nome". Podemos transformar para "Nome Sobrenome" com:
echo "Silva, João" | sed -E 's/(.*), (.*)/\2 \1/'
Aqui, (.*) captura o sobrenome e o nome, e depois os reordenamos. Sem a opção -E, precisaríamos escapar os parênteses: sed 's/\(.*\), \(.*\)/\2 \1/'.
As backreferences também são úteis para substituir padrões repetidos. Por exemplo, para colocar uma tag HTML em volta de palavras em negrito (que já estão entre asteriscos), podemos usar:
echo "*importante* e *urgente*" | sed -E 's/\*([^*]+)\*/\1<\/strong>/g'
Nesse caso, ([^*]+) captura o conteúdo entre asteriscos, e a backreference \1 o coloca dentro da tag. Esse tipo de transformação é comum em processamento de texto.
Edição in-place (-i)
A opção -i do sed permite editar o arquivo diretamente, sem precisar redirecionar a saída para um arquivo temporário. Por exemplo, para substituir todas as ocorrências de "foo" por "bar" no arquivo config.txt, sem criar um novo arquivo, usamos:
sed -i 's/foo/bar/g' config.txt
É importante notar que o sed -i modifica o arquivo original, o que pode ser perigoso se você cometer um erro. Para maior segurança, você pode criar um backup automático especificando uma extensão, como -i.bak, que gera um arquivo de backup com a extensão .bak antes da edição:
sed -i.bak 's/foo/bar/g' config.txt
Isso cria config.txt.bak com o conteúdo original, e config.txt com as alterações. Essa prática é recomendada quando você não tem certeza do resultado.
Outra dica: para testar antes de aplicar, rode o comando sem -i e verifique a saída. Se estiver correto, adicione -i para aplicar de fato.
Exemplos
Vamos combinar os recursos vistos para resolver problemas comuns. Suponha que temos um arquivo de log com linhas no formato:
2025-03-15 10:30:00 ERRO: falha na conexão
2025-03-15 10:31:00 INFO: tentativa de reconexão
2025-03-15 10:32:00 ERRO: timeout
Queremos deletar todas as linhas que contenham "ERRO" e inserir uma linha de aviso antes de cada linha "INFO". Podemos fazer com um único comando sed:
sed -e '/ERRO/d' -e '/INFO/i AVISO: operação em andamento' log.txt
Outro exemplo: transformar um arquivo CSV com campos separados por vírgula em um formato tabular. Suponha que temos:
Nome,Idade,Cidade
João,30,São Paulo
Maria,25,Rio de Janeiro
Podemos usar grupos para reordenar os campos: queremos "Cidade - Nome (Idade)". O comando:
sed -E 's/^([^,]+),([^,]+),([^,]+)$/\3 - \1 (\2)/' pessoas.csv
Isso captura cada campo e reordena. Para aplicar em um arquivo e salvar, usamos -i.
Por fim, para inserir uma linha de cabeçalho no início de um arquivo, podemos usar 1i:
sed -i '1i # Configuração gerada automaticamente' config.txt
Esses exemplos mostram como o sed pode ser usado para edições complexas de forma eficiente e direta.
Boas práticas
Ao trabalhar com sed avançado, sempre teste seus comandos em um arquivo de amostra antes de aplicar em massa. Use sed -n 'p' para imprimir apenas o que você quer ver, ou redirecione a saída para um arquivo temporário. Prefira usar a opção -E para expressões regulares extendidas, pois é mais legível e menos propensa a erros de escape. E lembre-se de fazer backup com -i.bak quando editar arquivos importantes.
Referências
- GNU sed manual
- GNU sed: Extended regexps
- GNU sed: In-place editing
- GNU sed: Back-references and Subexpressions
- GNU sed: Delete command
- GNU sed: Insert command
- GNU sed: Append command
- GNU sed: Other commands
- GNU sed: Examples
- GNU sed: Reporting bugs
Exercícios
- Dado o arquivo
dados.txtcom linhas como "joao:30:sao paulo", usesedpara deletar todas as linhas que contenham "30" (idade). - Escreva um comando
sedque insira a linha "" antes de cada linha que comece com "✓ Resposta:sed '/^(lembre-se de escapar os caracteres especiais se necessário).' arquivo.html - Use grupos e backreferences para transformar linhas no formato "primeiro ultimo" para "ultimo, primeiro". Por exemplo, "João Silva" deve virar "Silva, João".
✓ Resposta:sed -E 's/^([^ ]+) ([^ ]+)$/\2, \1/' nomes.txt(assumindo apenas dois campos).- Explique o que faz o comando
sed -i.bak 's/foo/bar/g' config.txte qual a importância do sufixo .bak.✓ Resposta: O comando substitui todas as ocorrências de "foo" por "bar" no arquivo config.txt, editando-o in-place. O sufixo .bak faz com que o sed crie um backup do arquivo original com o nome config.txt.bak antes de modificar, permitindo restaurar o original se necessário.- Crie um comando
sedque adicione uma linha de rodapé "" após a última linha de um arquivo. Dica: use o endereço$.✓ Resposta:sed '$a ' arquivo.txt(o endereço $ representa a última linha, e o comando a insere após ela).
sed '/:30:/d' dados.txt (ou sed '/:30/d' dados.txt se não houver outros campos com 30). Lembre-se de que o padrão deve ser específico para não deletar linhas erradas.