sriram
sriram

Reputation: 9032

How do I fetch lines before/after the grep result in bash?

I want a way to search in a given text. For that, I use grep:

grep -i "my_regex"

That works. But given the data like this:

This is the test data
This is the error data as follows
. . . 
. . . .
. . . . . . 
. . . . . . . . .
Error data ends

Once I found the word error (using grep -i error data), I wish to find the 10 lines that follow the word error. So my output should be:

. . . 
. . . .
. . . . . . 
. . . . . . . . .
Error data ends

Are there any way to do it?

Upvotes: 229

Views: 317389

Answers (5)

vjb
vjb

Reputation: 11

This may help you with finding an exact string before and after matching strings in a command.

You'll have to use two grep commands, using the pipe "|" operator. The command in the first pipe uses grep to print out all the text that appears a specified number of lines before the matching string, and an additional pipe operator makes grep to output the exact text after the matching string, ignoring the exact text that appears before or after the targeted string, further narrowing down the output.

Here's the template combination command that outputs only a specific string that's located specified number of lines before the specified string in the first "grep -B" pipe (replace the text between the {} symbols with your own):

{command-with-desired-output} | grep -B {number-of-lines-between-text-after-and-wanted-text} '{matching-string-after-wanted-value}' | grep -oP '(?<={exact-string-before-wanted-value}).*')

The "grep -B {number}" parameter prints all the contents for a desired number of lines that appear before the matching string, including the line matched, while cutting off everything that appears after the desired number of lines is reached - use "grep -A" if the desired value appears after the matching string.

The second grep command. "grep -oP", finds the matching string and prints everything after it until it reaches the end of the current line, while excluding the matching string.

Example command I used to find the Sink Input of a gmediarender sink:

pactl list sink-inputs | grep -B 20 'application.name = "gmediarender"' | grep -oP '(?<=Sink Input #).*')

An easy way to find how many lines before the matched string there are is to paste the output of just the grep -B command into gedit (you can use CTRL+SHIFT+C to copy highlighted text from the terminal, or right-click and copy), and read the amount of lines there - it will appear in the lower right corner of gedit's window as "Ln".

sudo apt-get install -y gedit

Upvotes: 1

Charlotte Russell
Charlotte Russell

Reputation: 1475

This prints 10 lines of trailing context after matching lines

grep -i "my_regex" -A 10

If you need to print 10 lines of leading context before matching lines,

grep -i "my_regex" -B 10

And if you need to print 10 lines of leading and trailing output context.

grep -i "my_regex" -C 10

Example

user@box:~$ cat out 
line 1
line 2
line 3
line 4
line 5 my_regex
line 6
line 7
line 8
line 9
user@box:~$

Normal grep

user@box:~$ grep my_regex out 
line 5 my_regex
user@box:~$ 

Grep exact matching lines and 2 lines after

user@box:~$ grep -A 2 my_regex out   
line 5 my_regex
line 6
line 7
user@box:~$ 

Grep exact matching lines and 2 lines before

user@box:~$ grep -B 2 my_regex out  
line 3
line 4
line 5 my_regex
user@box:~$ 

Grep exact matching lines and 2 lines before and after

user@box:~$ grep -C 2 my_regex out  
line 3
line 4
line 5 my_regex
line 6
line 7
user@box:~$ 

Reference: manpage grep

-A num
--after-context=num

    Print num lines of trailing context after matching lines.
-B num
--before-context=num

    Print num lines of leading context before matching lines.
-C num
-num
--context=num

    Print num lines of leading and trailing output context.

Upvotes: 73

Ray Toal
Ray Toal

Reputation: 88378

The way to do this is near the top of the man page

grep -i -A 10 'error data'

Upvotes: 11

Desislav Kamenov
Desislav Kamenov

Reputation: 1203

Try this:

grep -i -A 10 "my_regex"

-A 10 means, print ten lines after match to "my_regex"

Upvotes: 8

Jon Lin
Jon Lin

Reputation: 143876

You can use the -B and -A to print lines before and after the match.

grep -i -B 10 'error' data

Will print the 10 lines before the match, including the matching line itself.

Upvotes: 386

Related Questions