Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have the following text:

  A
  Hello
  world
  B
  Hello
  world
  C
  Hello
  world

I know that I can replace Hello by Hi using sed:

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

but this replace each Hello with Hi:

  A
  Hi
  world
  B
  Hi
  world
  C
  Hi
  world

what I really want is to replace only the Hello after B:

  A
  Hello
  world
  B
  Hi
  world
  C
  Hello
  world

so I have tried this:

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

but nothing happened, How can I do this?

Note: There are some white-spaces on the beginning of each line of the file.

share|improve this question

3 Answers 3

up vote 4 down vote accepted

Something like:

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

That assumes there are no consecutive Bs (one B line followed by another B line).

Otherwise, you could do:

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

The sed equivalent would be:

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

To replace the second word after B, or to replace world with universe only if two lines above contained B:

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

To generalise it to n lines above:

awk -v n=12 'l[NR%n] ~ /B/ {gsub("foo", "bar")}; {print; l[NR%n]=$0}'
share|improve this answer
    
it didn't work, I guess because the file have white-spaces on the beginning of each line –  Networker Aug 7 at 9:03
1  
@Networker, see edit. You could also use /B/ if you only need to check that the line contains B or /B$/ to check that it ends in B. –  Stéphane Chazelas Aug 7 at 9:19
    
Thanks this worked but How can I do the changes inline (to the file) using awk –  Networker Aug 7 at 9:21
1  
@Networker, with GNU awk 4.1.0 and above, use awk -i inplace '...'. –  Stéphane Chazelas Aug 7 at 9:32
1  
@Networker, Not easily. Use awk or perl when it gets tricky in sed. (perl also has in-place editing with -i, that's where GNU sed copied it from). –  Stéphane Chazelas Aug 7 at 10:06

You can add command to find white before and after Bs

Assuming u1 is

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

use the command

sed '/^[ ]*B[ ]*$/{n;s/Hello/Hi/;}' u1
A
Hello
world
 B
Hi
world
C
Hello
world
  B
Hi
world
share|improve this answer

This sed can handle the case when you have two consecutive B:

$ sed ':a
/B$/{$!N;/\n[[:blank:]]*Hello$/!ba;s/Hello/Hi/}
' file
share|improve this answer
    
Note that /[[:blank:]]*B$/ is the same as /B$/. That syntax implies GNU sed. –  Stéphane Chazelas Aug 7 at 9:52
    
@StéphaneChazelas: Thanks, removed it. –  cuonglm Aug 7 at 9:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.