1

I have a file like below

Event1
A
B
C
Event2
CC
CC
DD
Event1
E
N
D
Event2 

Now I could sed between Event 1 and Event 2 and able to take all the lines between those but what I want is, if the Sed can output only if the lines between Event1 and Event2 has "B" as a content. So my output looks like

Event1
A
B
C
Event2
Senthil
  • 21

1 Answers1

4
sed -n '/Event1/,/Event2/H;/Event2/{x;/B/p}' filename

Explanation:

  • the sed programm has two parts: /Event1/,/Event2/H and /Event2/{x;/B/p}.
  • First part: /Event1/,/Event2/ matches all lines between Event1 and Event2 inclusive. the H puts all those lines in the so called "hold space".
  • Second Part: /Event2/{x;/B/p} if line contains Event2 then execute the command group {x;/B/p}.
  • The command group also has two parts: x and /B/p.
  • x takes everything from "hold space" and puts it in "pattern space".
  • /B/p prints the pattern space if there is a B in it.

The idea in human language: take note of every line between Event1 and Event2. If you see Event2 then look at all the lines you just noted. If there is a B in it then print. Otherwise ignore.


Note the above sed program has a "bug".

If the input looks like this:

Event1x
A
B
C
Event2x
CC
CC
DD
Event1y
E
N
D
Event2y
CC
CC
DD
Event1z
X
B
X
Event2z

The output will look like this:

$ sed -n '/Event1/,/Event2/H;/Event2/{x;/B/p}' foo

Event1x
A
B
C
Event2x
Event2y
Event1z
X
B
X
Event2z

Note the Event2y and also the first empty line. This is because of sed peculiarities.

This modification of the sed progam replaces the Event2y with an empty line. which is basically the same reason for the first empty line.

sed -n '/Event1/,/Event2/H;/Event2/{s/.*//;x;/B/p}' filename

Example output

$ sed -n '/Event1/,/Event2/H;/Event2/{s/.*//;x;/B/p}' filename

Event1x
A
B
C
Event2x

Event1z
X
B
X
Event2z

The empty line can be fixed with even more sed-fu but I will need more reputation points to wrap my head around that.


Learn more sed!!1

Lesmana
  • 27,439
  • Thank you .. Now instead of value "B" , I have a value "B D" . When there is a space in the line I need to grep , the above one doesn't seem to work .. I tried as below

    sed -n '/Event1/,/Event2/H;/Event2/{s/.*//;x;/"B D"/p}' filename

    – Senthil Jan 05 '17 at 05:02
  • don't put quotes around B D. like this {s/.*//;x;/B D/p} – Lesmana Jan 05 '17 at 18:33