Posso substituir a terceira ocorrência de uma string por:
sed 's/OLD/NEW/3'
ou, com a implementação GNU de sed
, todas as ocorrências começando na terceira com:
sed 's/OLD/NEW/3g'
Mas como faço para substituir as últimas 3 (ou n) ocorrências?
A maneira mais simples de alterar as três últimas instâncias de uma string que corresponde a um padrão específico é reverter cada linha de entrada e substituir a string invertida:
Pode haver maneiras melhores de fazer isso se o formato específico das linhas relevantes for conhecido. Por exemplo, na string de teste que uso acima, poderíamos simplesmente ter substituído
OLD OLD OLD
porNEW NEW NEW
.Observe também que, como as expressões regulares são aplicadas da esquerda para a direita, a substituição da string invertida pode exigir um padrão diferente da reversão ingênua da expressão original. Como exemplo, considere que a substituição das duas primeiras letras em
abab
, quando invertida, deve substituir as duas últimas letras embaba
.A inversão de uma linha pode ser feita
sed
assim, usando@
como um caractere pivô para dividir a string em uma parte não invertida e uma parte invertida:Uma abordagem poderia ser:
Com
perl
, fazendo a substituição duas vezes, uma vez e sem alteração para registrar o número de ocorrências, e uma segunda vez para substituir apenas a (n-2)-ésima pela n- ésima ocorrência:Para strings arbitrárias e número máximo de ocorrências:
s/OLD/$&/g
substitui todas as ocorrências por si mesmas ($&
contém o que foi correspondido comosed
's&
) e retorna o número de substituições. Alternativamente, você pode usars/OLD\K//g
which substitui o Nothing AfterOLD
por Nothing ,\K
sendo usado para marcar o início do que está sendo substituído.Usando GNU awk para
patsplit()
:Você pode fazer o mesmo em qualquer awk com um loop
while (match())
ouwhile(index())
esubstr()
s, é apenas um pouco mais de código para escrever. O acima trataOLD
como um regexp, se não é isso que você deseja, use umwhile(index())
loop ou escreva código para escapar de qualquer metacharsOLD
que possa conter, por exemplo, em qualquer awk usando strings literais:Embora não exista uma opção sed direta para esta operação, aqui está uma abordagem prática: substitua a última ocorrência da string por:
Como n geralmente é pequeno, você pode simplesmente canalizar isso para o mesmo comando n vezes:
ou mais simplesmente repita este comando n vezes:
(observe que neste caso o input_file muda)