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

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

[ Hits: 3.860 ]

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

Javascript - pegar um elemento aleatório de uma lista

Instalando Docker no Debian 10 Buster

Como somar todos os números contidos num arquivo texto

Desativando popups "O sistema detectou um problema no aplicativo" no Ubuntu

Usando a chave UNIQUE para campos em uma tabela MySQL

Leitura recomendada

Expressão regular para validar um IP

Informações completas sobre os arquivos numa pasta

Screen (janelas) no modo shell?

Introdução ao awk

Obtendo a cotação do Bitcoin com SED

  

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