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

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

[ Hits: 793 ]

Blog: https://youtube.com/c/cotidianohackeado

 


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

Lendo arquivos Markdown no terminal (*.md)

Como aumentar ou reduzir a velocidade de um vídeo via linha de comando

Criando texto "hacker" com SED

Escolhendo quais colunas exibir no comando top

Evitando vulnerabilidades em seu servidor NFS

Leitura recomendada

Screen (janelas) no modo shell?

Ações condicionais no SED

Redirecionamento no Shell

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

Como fazer "quit" no SED

  

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


Muito bom.

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



Contribuir com comentário