Grep whole paragraphs of a text containing a specific keyword

Kyriakos P. picture Kyriakos P. · Sep 3, 2015 · Viewed 10k times · Source

My goal is to extract the paragraphs of a text that contain a specific keyword. Not just the lines that contain the keyword, but the whole paragraph. The rule imposed on my text files is that every paragraph starts with a certain pattern (e.g. Pa0) which is used throughout the text only in the start of the paragraph. Each paragraph ends with a new line character.

For example, imagine I have the following text:

Pa0 
This is the first paragraph bla bla bla
This is another line in the same paragraph bla bla 
This is a third line bla bla 

Pa0
This is the second paragraph bla bla bla
Second line bla bla My keyword is here!
bla bla bla 
bla 

Pa0
Hey, third paragraph bla bla bla!
bla bla 

Pa0
keyword keyword
keyword
Another line! bla 

My goal is to extract these paragraphs that contain the word "keyword". For example:

Pa0
This is the second paragraph bla bla bla
Second line bla bla My keyword is here!
bla bla bla 
bla 

Pa0
keyword keyword
keyword
Another line! bla 

I can use e.g. grep for the keyword and -A, -B or -C option to get a constant number of lines before and/or after the line where the keyword is located but this does not seem enough since the beginning and end of the text block depends on the delimiters "Pa0" and "\n".

Any suggestion for grep or another tool (e.g. awk, sed, perl) would be helpful.

Answer

hek2mgl picture hek2mgl · Sep 3, 2015

It is simple with awk:

awk '/keyword/' RS="\n\n" ORS="\n\n" input.txt

Explanation:

Usually awk operates on a per line basis, because the default value of the record separator RS is \n (a single new line). By changing the RS to two new lines in sequence (an empty line) we can easily operate on a paragraph basis.

/keyword/ is a condition, a regex. Since there is no action after the condition awk will simply print the unchanged record (the paragraph) if it contains keyword.

Setting the output record separator ORS to \n\n will separate the paragraphs of output with an empty line, just like in the input.