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!