Demontager February 2016

Grep text between patterns using bash

I need to sort data which reside in txt file. The sample data is as follows:

======
Jhon 
Doe 
score -
------  
======
Ann 
Smith 
score + 
------
======
Will 
Marrow 
score - 
------

And I need to extract only sections where score + is defined. So the result should be

======
Ann 
Smith 
score + 
------

Answers


Kent February 2016

give this oneliner a try:

awk -v RS="==*" -F'\n' '{p=0;for(i=1;i<=NF;i++)if($i~/score \+/)p=1}p' file

with the given data, it outputs:

Ann 
Smith 
score + 
------

The idea is, take all lines divided by ====... as one multiple-line record, and check if the record contains the searching pattern, print it out.


dawg February 2016

Given:

$ echo "$txt"
======
Jhon 
Doe 
score -
------  
======
Ann 
Smith 
score + 
------
======
Will 
Marrow 
score - 
------

You can create a toggle type match in awk to print only the section that you wist:

$ echo "$txt" | awk '/^=+/{f=1;s=$0;next} /^score \+/{f=2} f {s=s"\n"$0} /^-+$/ {if(f==2) {print s} f=0}'
======
Ann 
Smith 
score + 
------


mauro February 2016

I would try this one:

$ grep -B3 -A1 "score +" myfile

It means... grep three lines Before and one line After "score +".


Benjamin W. February 2016

Sed can do it as follows:

sed -n '/^======/{:a;N;/\n------/!ba;/score +/p}' infile 
======
Ann 
Smith 
score + 
------

where -n prevents printing, and

/^======/ {       # If the pattern space starts with "======"
    :a            # Label to branch to
    N             # Append next line to pattern space
    /\n------/!ba # If we don't match "------", branch to :a
    /score +/p    # If we match "score +", print the pattern space
}

Things could be more properly anchored with /\n------$/, but there are spaces at the end of the lines, and I'm not sure if those are real or copy-paste artefacts – but this work for the example data.


Ed Morton February 2016

With GNU awk for multi-char RS:

$ awk -v RS='=+\n' '/score \+/' file
Ann 
Smith 
score + 
------


CodeGnome February 2016

Use Grep Context Flags

Assuming you have a truly fixed-format file, you can just use fgrep (or GNU or BSD grep with the speedy --fixed-strings flag) along with the the --before-context and --after-context flags. For example:

$ fgrep -A1 -B3 'score +' /tmp/foo 
======
Ann 
Smith 
score + 
------

The flags will find your match, and include the three lines before and one line after each match. This gives you the output you're after, but with a lot less complexity than a sed or awk script. YMMV.

Post Status

Asked in February 2016
Viewed 1,230 times
Voted 4
Answered 6 times

Search




Leave an answer