SED - substituir apenas a ocorrência N de uma string

Publicado por Fábio Berbert de Paula em 08/06/2020

[ Hits: 3.855 ]

Blog: https://fabio.automatizando.dev

 


SED - substituir apenas a ocorrência N de uma string



Suponha que você precisa fazer uma dieta e possui o seguinte cardápio semanal:

echo churrasco churrasco churrasco churrasco churrasco churrasco churrasco

O objetivo é substituir os pratos do final de semana, que no caso seriam as ocorrências 6 e 7, por salada. Antes:

churrasco churrasco churrasco churrasco churrasco churrasco churrasco

Depois:

churrasco churrasco churrasco churrasco churrasco salada salada

Com o sed podemos fazer assim:

echo churrasco churrasco churrasco churrasco churrasco churrasco churrasco| sed 's/churrasco/salada/6; s/churrasco/salada/6'

Repare que usei o padrão 's/antes/depois/N', onde N é o número da ocorrência. Porém repeti a ocorrência 6 duas vezes. O motivo é que na segunda passada, o churrasco de domingo é a ocorrência 6, visto que sábado não é mais churrasco.

Também posso usar a seguinte sintaxe:

echo churrasco churrasco churrasco churrasco churrasco churrasco churrasco| sed 's/churrasco/salada/6g'

que significa alterar todas as ocorrências a partir da N=6.

Usando o sed via arquivo

O grande problema na sintaxe anterior é que ela não funciona exatamente assim para arquivos, visto que o sed trata uma linha por vez. Então podemos contornar o problema usando uma sintaxe um pouco mais avançada...

Dado um arquivo "cardapio.txt" com o seguinte conteúdo:

churrasco
churrasco
churrasco
churrasco
churrasco
churrasco
churrasco

Se executarmos o comando abaixo não acontecerá nada, pois só há uma ocorrência de churrasco por linha ao invés de sete:

sed 's/churrasco/salada/6' cardapio.txt
churrasco
churrasco
churrasco
churrasco
churrasco
churrasco
churrasco


A solução é a sintaxe abaixo, cuja explicação vem a seguir:

sed ':a ; N; $! ba ; s/churrasco/salada/6g' cardapio.txt
churrasco
churrasco
churrasco
churrasco
churrasco
salada
salada


Explicando:
  • :a - crie uma "label" chamada "a" no buffer de memória;
  • N - leia a próxima linha e a armazene;
  • $! - enquanto não for fim de arquivo;
  • ba - retorne (back) para a label "a".

Com esse truque o sed armazenou todo o conteúdo do arquivo em memória e irá processá-lo com um conteúdo só ao invés de ler linha por linha. Na verdade ele leu linha por linha ( :a; N; $! ba ), mas só depois de ler todas elas que ele processou a expressão regular.

Espero ter explicado com clareza o suficiente.

Até a próxima!

Outras dicas deste autor

E-book GRATUITO de Shell Script do Júlio Neves

Como desabilitar o protocolo SSL3 no Nginx

Erro: user in plugdev group; are your udev rules wrong? [Resolvido]

Como fazer print() sem quebra de linha em Python

Erro: "ImportError: No module named PIL" [Resolvido]

Leitura recomendada

sed - Eliminando linhas em branco

SED - texto para maiúsculas, minúsculas, pascal case e camel case

Como remover parêntesis dos nomes de arquivos

Busca por string dentro dos arquivos

Informações completas sobre os arquivos numa pasta

  

Comentários
[1] Comentário enviado por maurixnovatrento em 08/06/2020 - 11:53h


Muito bom.

___________________________________
Conhecimento não se Leva para o Túmulo.



Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts