Você pode fazer isso com sed
em uma pilha ...
sed '/match$/N
s/\n/&INSERT&/3;t
$n;N;P;D'
Isso inseria INSERT
após cada terceira ocorrência não sequencial de match
na entrada. É a maneira mais eficiente que eu sei fazer isso com sed
porque ele não tenta armazenar todas as linhas que ocorrem entre diferentes matches
, nem requer trocas de buffer ou comparações back-ref , mas simplesmente incrementa o único meio de contagem de sed
- seu número de linha através de seu ciclo de linha.
Há alguma sobrecarga adicionada, é claro - com cada espaço de padrão de jogo ficando um pouco maior - mas ainda é o mesmo fluxo, e não há back-tracking. É apenas primeiro a entrar, primeiro a sair - o que, na minha opinião, é um método muito adequado para sed
. De fato, em vez de voltar para verificar se há uma correspondência, sed
pode avançar mais à frente para cada partida. Estou um pouco orgulhosa disso e não sei porque nunca pensei nisso antes.
A versão acima, no entanto, iria apertar repetições até certo ponto, porque funciona apenas uma linha atrás da entrada. E a solução para isso é avançar ainda mais e requer apenas um pouco de complexidade adicional na forma de um loop de curto-circuito b
ranch :l
abel dentro do loop N;P;D
para mantê-lo atualizado.
Funciona assim:
seq 100000| sed -ne':n
s/\n/&\tCheck&\t/5p;t
N;/0000$/bn' -eD
... que, para mim, imprime ...
49995
49996
49997
49998
49999
Check
50000
99995
99996
99997
99998
99999
Check
100000
Veja, para manter a contagem, ele incrementa seu buffer de linha para cada ocorrência de match
e insere outra linha em sua janela deslizante no espaço padrão. Dessa forma, tudo o que é necessário para verificar se a correspondência foi encontrada é tentar substituir o caractere de ewline s///
nth
\n
no espaço padrão. Se isso puder ser feito, encontraremos n matches
até o momento, e t
est poderá desvincular-nos da iteração atual e limpar o incremento completamente.
No exemplo acima, o buffer é incrementado uma vez para cada padrão de espaço que termina com a string 0000
. Quando 5 desses são encontrados, sed
imprime o espaço de padrão atual - e todo o buffer - e limpa o contador.
Para você:
printf DCR\n| tee - - - - - |
sed -e:n -e's/\n/&\tCheck&\t/2;t
$n; N;/DCR$/bn' -eP\;D
DCR
DCR
Check
DCR
DCR
DCR
Check
DCR
Agora, se você quiser marcar apenas a ocorrência nth
, também é fácil:
printf DCR\n |
tee - - - - - - - - -|
sed -e:n -e's/\n/&\tCheck&\t/3;te
$n; N;/DCR$/bn' -e'P;D;:e
n;be'
... se você realmente olhar para isso, pode ocorrer a você que nós apenas mal arranhamos a superfície aqui ...
DCR
DCR
DCR
Check
DCR
DCR
DCR
DCR
DCR
DCR
DCR