Substitui uma palavra após uma linha significativa e espaços em branco (inline) usando sed?

3

Eu tenho o seguinte texto:

  A
  Hello
  world
  B
  Hello
  world
  C
  Hello
  world

Eu sei que posso substituir Hello por Hi usando sed :

sed 's/Hello/Hi/g' -i test

mas isso substitui cada Hello por Hi :

  A
  Hi
  world
  B
  Hi
  world
  C
  Hi
  world

o que eu realmente quero é substituir apenas o Hello após B :

  A
  Hello
  world
  B
  Hi
  world
  C
  Hello
  world

então eu tentei isso:

sed 's/"B\nHello"/"B\nHi"/g' -i test

mas nada aconteceu, como posso fazer isso?

Nota: Existem alguns espaços em branco no início de cada linha do arquivo.

    
por Networker 07.08.2014 / 10:55

3 respostas

4

Algo como:

sed '/^[[:blank:]]*B$/{n;s/Hello/Hi/g;}'

Isso assume que não há B s consecutivos (uma linha B seguida por outra linha B ).

Caso contrário, você poderia fazer:

awk 'last ~ /^[[:blank:]]*B$/ {gsub("Hello", "Hi")}; {print; last=$0}'

O sed equivalente seria:

sed 'x;/^[[:blank:]]*B$/{
       g;s/Hello/Hi/;b
     }
     g'

Para substituir a segunda palavra após B ou para substituir world por universe apenas se duas linhas acima contiverem B :

awk 'l2 ~ /B/ {gsub("world","universe")}; {print; l2=l1; l1=$0}'

Para generalizar para n linhas acima:

awk -v n=12 'l[NR%n] ~ /B/ {gsub("foo", "bar")}; {print; l[NR%n]=$0}'
    
por 07.08.2014 / 10:57
1

Você pode adicionar o comando para encontrar o branco antes e depois do Bs

Supondo que u1 é

A
Hello
world
 B
Hello
world
C
Hello
world
  B   (<-tailing whites)
Hello
world

use o comando

sed '/^[ ]*B[ ]*$/{n;s/Hello/Hi/;}' u1
A
Hello
world
 B
Hi
world
C
Hello
world
  B
Hi
world
    
por 07.08.2014 / 11:20
1

Este sed pode lidar com o caso quando você tem dois B consecutivos:

$ sed ':a
/B$/{$!N;/\n[[:blank:]]*Hello$/!ba;s/Hello/Hi/}
' file
    
por 07.08.2014 / 11:24