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

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

[ Hits: 4.447 ]

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

Carteira de Bitcoin Electrum no Linux

Conheça o comando look

Como remover senhas de arquivos PDF por linha de comando

Como instalar Opera no Debian 10 Buster

Inicialização do Sistema

Leitura recomendada

Múltiplas expressões no SED

Testando se uma variável é número em shell script

sed - Eliminando linhas em branco

Screen (janelas) no modo shell?

Sed - como salvar alterações no arquivo

  

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