Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Extending grep like search 2also show 2 previous lines 4each occurance

Status
Not open for further replies.

Sudmill

Programmer
Apr 20, 2001
65
GB
Help is really needed .. i did awk a long time ago at Uni and therefore think what im trying to acheive is possible, but know that my awk skills are now non existant!

Basically, Im doing a grep of a file at the moment, which outputs each line with the text. What I want it to do is also output the preceeding 1 or 2 lines to the sucessful search?

Anyone fancy the challenge?

Many thanks in advance,

John.
Cheers

John (Sudmill)
 

#------------- getPattern.awk -------------------

BEGIN {
line1=""
line2=""
}

/pat/ {
printf("--\n%s\n%s\n%s\n--\n", line1, line2, $0);
}

{
line1=line2
line2=$0
}

#-------------------- getPattern.txt ---------------
line 1
line 2
line 3
pattern2find
line5
pattern2find
line7
line8
line9
pattern2find

# -------------------------------------------


nawk -v pat="pattern2find" -f getPattern.awk getPattern.txt
 
I took the sed challenge and got

# found and 1 line prior
sed -n -e '/pattern/{x;1!p;g;p;D;}' -e 'h' "$@"

# found and 2 lines prior
sed -n '
/pattern/{
x
p
b pos1
}
x
:pos1
s/.*\n//
x
/pattern/p
H
g
' "$@"

I'd go with the awk choices because awk is easier to read and understand. It is also a tiny bit easier on the CPU although a tiny bit slower than sed.

Cheers,
ND
 
The grep utility has a flag that accepts context
based searches:

Try grep -B2 "string" filename

Another way used in the past is a kludged shell function
along the lines of:

context() {
str=${1:-""}
file=${2:-""}

lines=`grep -n $str $file | sed 's/:.*//'

for xx in $lines
do
awk -v stat=$xx ' BEGIN {
printf "Depth of search before match: "
getline D < &quot;-&quot;
printf &quot;Depth of search after match: &quot;
getline A < &quot;-&quot;
}

{
if (A && D) {
if (NR >= (stat - D) && NR <= (stat - A)) {
lines = $0
}
print lines
}
}'
return $?
}

ex:
stuff=`context &quot;bogus&quot; &quot;/home/user/foo&quot;` ; echo $stuff
 
Thanks guys .... phew ... thats some lot of code. I cant believe the response !

Im not acutally able to have any code resident on the (aix) server, so am I right in thinking that at least the awk can be concatenated on one command line for a copy and paste approach (!!!) ?

Cheers

John (Sudmill)
 
The sed solutions will work as cut/paste okay by replacing by just chaning the pattern/regexp to seek and the &quot;$@&quot; to you filename(s) or stdin. The one-liner will be easy and the multi-liner will work fine in sh & ksh but in csh you need a space and back-slash at the end of every line but the last (and will be anoyed in the process). Can you still set up aliases or functions in your shell to do this?

Cheers,
ND
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top