Grep a pattern and print following n lines

Hi all,

I am struck with the below requirement. I need to grep a particular pattern in a file and then print next n lines of it for further processing.
I have used the below code

grep -A 3 "pattern" filename

But it is throwing error as below.

grep: illegal option -- A

Can anyone help me with some alternates for this.

Thanks.

That's an option to GNU grep, which not all systems have. What is your system?

Anyway, this should do:

awk 'PAT ~ $0 { N=LINES } (N--) > 0' LINES=5 PAT="qwerty" inputfile

Use nawk on Solaris.

Hi Corona,
Thanks for the reply. My system is Solaris . But i need this for AIX too
I am getting error when used with awk and no output when used with nawk as below

$ awk 'PAT ~ $0 { N=LINES } (N--) > 0' LINES=5 PAT="ISEND" sqloutput1.log
awk: syntax error near line 1
awk: bailing out near line 1
$ nawk 'PAT ~ $0 { N=LINES } (N--) > 0' LINES=5 PAT="ISEND" sqloutput1.log
$

Hello ssk250,

Could you please use /usr/xpg4/bin/awk , and /usr/xpg6/bin/awk in place of awk this should work.

Thanks,
R. Singh

1 Like

Sorry, there was a mistake in my code.

awk '$0 ~ PAT { N=LINES } (N--) > 0' LINES=5 PAT="ISEND" sqloutput1.log
1 Like

(N--) > 0 can overflow with large files. Better (N && N--) !

1 Like

Hi All,

Thanks All. The below script worked for me

/usr/xpg4/bin/awk '$0 ~ PAT { N=LINES } (N--) > 0' LINES=5 PAT="ISEND" sqloutput1.log

Just want to know... In a similar way how the lines before this pattern can be printed.

Perhaps something like:

/usr/xpg4/bin/awk '
function pprev(		i) {
	for(i = (NR > LINES) ? NR - LINES + 1 : 1; i <= NR; i++) 
		print l[i % LINES]
	print ""
}
{	l[NR % LINES] = $0
}
$0 ~ PAT {
	pprev()
}' LINES=3 PAT='9' file

If file contains 100 lines numbered from 100 to 001:

100
099
098
098
...
003
002
001

the output produced is:

100
099

100
099
098

099
098
097

098
097
096

097
096
095

096
095
094

095
094
093

094
093
092

093
092
091

092
091
090

091
090
089

081
080
079

071
070
069

061
060
059

051
050
049

041
040
039

031
030
029

021
020
019

011
010
009

1 Like

The following shell command emulates the ggrep -E -A4 , and works on all Unix:

PATH=/usr/xpg4/bin:/bin:/usr/bin awk '$0~PAT {a=A+1} (a && a--)' A=4 PAT="ISEND" sqloutput1.log

Omit the A=x to have the normal grep -E behavior.

1 Like

Hi.

Some general alternatives, as opposed to single-purpose solutions:

Print lines above, below pattern-matched line (context, window); "only" string matching pattern
	1) GNU grep -A -B; ggrep on some Solaris

	2) peg, a perl script, does not use "-o" like GNU grep;
	allows -A, -B

	3) ack, a perl script, can use "-o" like GNU grep; allows -A,
	-B

	4) cgrep does not use "-o" like GNU grep; allows -nline,
	+nline for context like GNU grep -A, -B

	5) bool, prints context in bytes

	6) xtcgrep, extension of CPAN grep; allow -C context; allows -o;
	complicated calling sequence; http://freecode.com/projects/greppm

Best wishes ... cheers, drl

1 Like

The probably easiest way is to use good old sed instead of all the fancy tools:

sed -n '/<search-pattern>/ {;N;...N;p;}' /path/to/file

Put in x-1 "N"s to display x lines of text after the matched pattern.

I hope this helps.

bakunin

1 Like

Thanks ... ggrep is working on Solaris.

Problem solved. But the previous sed solution needs a fix; (at least on Solaris) it does not print at the end of a file, because the N command terminates the script. Therefore, each N is to be preceded by a $p .
The following works with a number for the trailing lines (here: 3).

sed -e '/^<search-pattern>/!d;:L' -e '$p;N;s/\n/&/3;t' -e 'bL' file

---------- Post updated at 10:19 AM ---------- Previous update was at 10:14 AM ----------

Hmm interesting, GNU sed prints at the end of the file, so the $p would print twice...
Which sed is correct?

1 Like

You objection is correct and it was my bad not to think my solution through to the end. GNU-sed - as it is so often is the case - gets it wrong (again).

bakunin

An alternative would be to use: $!N instead of N , which should give equal results with GNU sed..

1 Like