Como substituir a ocorrência de palavra em intervalos especificados usando o comando sed?

1
str="I want to abc replace a word abc in a sentence abc of file abc by giving abc specifying a abc multiple abc range to abc the sed abc command abc."

A palavra sting acima tem a palavra "abc" 10 vezes , quero substituir "abc" do 2nd-4th time e 6th-8th com a palavra "xyz" usando o comando sed.

após o comando sed na string str, str deve ter a seguinte aparência:

str="I want to abc replace a word xyz in a sentence xyz of file xyz by giving abc specifying a xyz multiple xyz range to xyz the sed abc command abc."
    
por Prashant BJ 01.02.2015 / 06:22

2 respostas

2

Não tenho certeza se é inteligente ou não, mas aqui está minha solução de sed do GNU:

sed 's/abc/nonABC/5;s/abc/nonABC/8g;s/abc/xyz/2g;s/nonABC/abc/g' <<<"$str"

Explicação:

sed '
    s/abc/nonABC/5;   # replace only 5th occurrence of 'abc' word with another word (i, e: 'nonABC') 
    s/abc/nonABC/8g;  # replace 8th to the next occurrences of 'abc' with another word too
    s/abc/xyz/2g;     # replace all occurrences of 'abc' word start from 2th place
    s/nonABC/abc/g    # get back the all changed 'abc' from 'nonABC'
' <<<"$str"           # from 'str' as input

E com awk e, claro, inteligente:

awk '{printf ( 2<=NR && NR<=8 && NR!=5 )?$0"xyz":$0RS}' RS='abc' <<<"$str"

Explicação:

  • RS='abc' define 'abc' como R ecord S eparator
  • se N umber de R ecord estiver entre 2 e 8 2<=NR && NR<=8 , mas não igual a 5 NR!=5 , imprima o registro atual $0 e substitua a palavra xyz , caso contrário, imprima o registro e abc em si. você pode usar $0"abc" no lugar de $0RS.

Se os seus intervalos forem semelhantes: [(2-4), (8-10), (12-15), (18-20), (26-29) ...] como você mencionou no comentário então awk é o melhor comando para este trabalho. Só você precisa especificar os intervalos como várias condições:

( (2<=NR && NR<=4) || (8<=NR && NR<=10) || (12<=NR && NR<=15) || (18<=NR && NR<=20) || (26<=NR && NR<=29) || (...) )
    
por devWeek 03.02.2015 / 21:39
2

Outra maneira de ajudar na expansão de chaves, você pode fazer:

sed '-es/abc/xyz/'{8..6} '-es/abc/xyz/'{4..2} <<<"$str"

Tenha em atenção que o intervalo deve ser sempre max primeiro em {max#..min#} , mesmo que os primeiros intervalos máximos devam ser especificados primeiro.

Você também pode especificar qual intervalo de posições deve substituir em {x,y,z} format, em que os números devem ser x>y>z :

sed '-es/abc/xyz/'{8,6,4,2} <<<"$str"

Observe que, se você usar o mesmo número {x,x} , isso causará um problema e substituirá a posição x novamente (BTW, para isso, há s/abc/xyz/X alternativa, onde X é o número da posição).

Eu aprendi isso com a resposta de Stéphane Chazelas no Unix.SE

    
por devWeek 23.03.2018 / 08:11