Como substituir toda nésima ocorrência de padrão usando sed SOMENTE

-1

Eu pesquisei em toda a web, mas não consigo encontrar nenhuma boa solução. Eu li em muitos fóruns que sed não é a ferramenta (mas awk é) para isso, mas não faz sentido para mim o porquê. Quer dizer, você pode fazer uma substituição simples para a ocorrência número 5, por exemplo, como: sed 's/pattern/replace/5' para substituir apenas a quinta instância. Por que não é possível sed do 's/pattern/replace/<every 5th occur>' para uma linha? Não é uma função básica ...

De qualquer forma, meu problema é que o software do nosso cliente é executado em um ambiente Windows que tem funções limitadas do Linux e, infelizmente, awk não está disponível no sistema. Instalar novos comandos NÃO é uma opção para a empresa por qualquer motivo.

Então, minha pergunta é, qual é a melhor maneira de usar sed e / ou misturado com o bash para substituir cada n-ésima ocorrência de um padrão por linha? Eu só tenho uma linha de qualquer maneira como eu já tirei todos os novos caracteres de linha. O bash for loop é o único caminho?

    
por Harry McKenzie 24.03.2018 / 09:36

2 respostas

4

Isn't that a basic function..

Obviamente, não é. Mas ainda é possível :

sed 's/a\([^a]*\($\|a[^a]*\($\|a[^a]*\($\|a[^a]*\($\|a\)\)\)\)\)/A/g'

Mais legível com -r , onde podemos eliminar as barras invertidas:

sed -r 's/a([^a]*($|a[^a]*($|a[^a]*($|a[^a]*($|a)))))/A/g' 

i.e. a , seguido por qualquer número de não a , seguido por qualquer fim de linha ou outro a , seguido por qualquer número de não a , etc. Tudo após o primeiro a é lembrado em .

BTW, se o Perl estiver disponível, você pode usar:

perl -pe 'BEGIN { @A = qw(a A) } s/a/$A[not $i++ % 5]/g'

% é o operador de módulo. $ i é incrementado com cada correspondência, a negação do módulo é 1, 0, 0, 0, 0, 1, etc., que é usada como o índice em @A escolhe o a ou A .

    
por choroba 24.03.2018 / 09:59
1

Simples sed e uma expansão de chaves:

sed '-es/pattern/replace/'{max..min..step} infile

substitua max por um número > = número de ocorrências de padrão , se você não sabe, defina-o como o maior número de caracteres em um maior linha no seu arquivo.

$ sed '-es/a/A/'{20..1..5} <<<"aaaa aaaa   a a a aa a a a aa aa"
aaaa Aaaa   a A a aa a A a aa aA

Para substituir a primeira ocorrência também, use abaixo:

$ sed '-es/a/A/'{{20..1..5},1} <<<"aaaa aaaa   a a a aa a a a aa aa"
Aaaa Aaaa   a A a aa a A a aa aA
    
por devWeek 24.03.2018 / 11:11