4

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.

3 Answers 3

5

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}'
8
  • it didn't work, I guess because the file have white-spaces on the beginning of each line
    – Nidal
    Commented Aug 7, 2014 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. Commented Aug 7, 2014 at 9:19
  • Thanks this worked but How can I do the changes inline (to the file) using awk
    – Nidal
    Commented Aug 7, 2014 at 9:21
  • 1
    @Networker, with GNU awk 4.1.0 and above, use awk -i inplace '...'. Commented Aug 7, 2014 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). Commented Aug 7, 2014 at 10:06
1

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
1

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

$ sed ':a
/B$/{$!N;/\n[[:blank:]]*Hello$/!ba;s/Hello/Hi/}
' file
1
  • Note that /[[:blank:]]*B$/ is the same as /B$/. That syntax implies GNU sed. Commented Aug 7, 2014 at 9:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .