1847502 Members
5349 Online
110265 Solutions
New Discussion

grep question

 
SOLVED
Go to solution
Jeff Picton
Regular Advisor

grep question

Is it possible to print out the line after the pattern found by grep.

i.e. grep x rc.log and print out the line after x (assuming x is terminated by a new line) ?
13 REPLIES 13
Pete Randall
Outstanding Contributor

Re: grep question

Jeff,

You can do this sort of thing with sed:

# print 1 line of context before and after regexp, with line number
# indicating where the regexp occurred (similar to "grep -A1 -B1")
sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h


I'm attaching the Handy One-Liners For Sed where I swiped that from.


Pete




Pete
Leif Halvarsson_2
Honored Contributor

Re: grep question

Hi,

Better to use awk:

awk '/DEVICE/ { getline a ; print a }' file_name
Sergejs Svitnevs
Honored Contributor
Solution

Re: grep question

try to use sed:
# more rc.log | sed -n '/x/{n;p;}';

where:
"n" - replace the pattern space with the Next line of input
"p" - Print the pattern space


Regards,
Sergejs
john korterman
Honored Contributor

Re: grep question

Hi,

you can make a small script where $1 is the string to search for and $2 is the file to search in:

#!/usr/bin/sh
grep -n "$1" "$2"| while read LINE
do
LINE_NO=$(echo $LINE | awk -F: '{print $1}')
head -$(($LINE_NO + 1)) $2 | tail -1
done

regards,
John K.
it would be nice if you always got a second chance
Jeff Picton
Regular Advisor

Re: grep question

On a different but related subject (if that means sense) how do I subtract two date values of the format 12:00:27 - 12:00:00 ?
H.Merijn Brand (procura
Honored Contributor

Re: grep question

All these don't cover the situation where the line printed would also match the patter, and thus should print the line after that.

# perl -ne'BEGIN{$p=shift;$p/qr/$p/;$x=<>}$x=~$p&&print;$x=$_' pattern file

d3:/tmp 115 > cat xx
Blah
Foo
Bar
Zap
Flunky
Boomer
Trip
Yoh!
Bzzt
Ahh
Aak
d3:/tmp 116 > perl -ne'BEGIN{$p=shift;$p/qr/$p/;$x=<>}$x=~$p&&print;$x=$_' a xx
Foo
Zap
Flunky
d3:/tmp 117 >

Enjoy, have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
H.Merijn Brand (procura
Honored Contributor

Re: grep question

Fetch A.Clay's just updated date Hammer from my https://www.beepz.com/personal/merijn/ or http://www.cmve.net/~merijn/ or use perl's modules -MDate::Calc or -MDate::Manip

Enjoy, have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
H.Merijn Brand (procura
Honored Contributor

Re: grep question

A simple example (script also attached):

a5:/pro/3gl/CPAN 102 > elapsed.pl -?
usage: elapsed stamp1 stamp2date/time date/time
a stamp is one of date (YYYYMMDD), a time (HH:MM:SS)
or a combination of both (date first).
both stamps should be declared the same
a5:/pro/3gl/CPAN 103 > elapsed.pl 20:30:40 21:32:43
Elapsed time: 1 hour(s) 2 minute(s) 3 second(s)
a5:/pro/3gl/CPAN 104 >


a5:/pro/3gl/CPAN 104 > cat elapsed.pl
#!/usr/bin/perl -w

use strict;

use Date::Calc qw(Delta_DHMS);

sub usage ()
{
print STDERR "usage: elapsed stamp1 stamp2date/time date/time\n",
" a stamp is one of date (YYYYMMDD), a time (HH:MM:SS)\n"
,
" or a combination of both (date first).\n",
" both stamps should be declared the same\n";
exit 0;
} # usage

@ARGV == 1 and $ARGV[0] eq "-?" || $ARGV[0] =~ m/^-+help$/ and usage;

@ARGV == 2 || @ARGV == 4 or usage;

my %d = (y1 => 2002, m1 => 1, d1 => 1, H1 => 12, M1 => 0, S1 => 0,
y2 => 2002, m2 => 1, d2 => 1, H2 => 12, M2 => 0, S2 => 0);

if ($ARGV[0] =~ m/^(\d{4})(\d\d)(\d\d)/) {
@d{qw(y1 m1 d1)} = ($1, $2, $3);
shift;
if (@ARGV > 2) {
@d{qw(H1 M1 S1)} = split m/\D/, shift;
defined $d{S1} or usage;
}
@d{qw(y2 m2 d2)} = (shift (@ARGV) =~ m/^(\d{4})(\d\d)(\d\d)/);
defined $d{d2} or usage;
if (@ARGV) {
@d{qw(H2 M2 S2)} = split m/\D/, shift;
defined $d{S2} or usage;
}
}
else {
@d{qw(H1 M1 S1)} = split m/\D/, shift;
defined $d{S1} or usage;
@d{qw(H2 M2 S2)} = split m/\D/, shift;
defined $d{S2} or usage;
}

my ($d, $h, $m, $s) = Delta_DHMS (@d{qw(y1 m1 d1 H1 M1 S1 y2 m2 d2 H2 M2 S2)});
print "Elapsed time:";
$d and print " $d day(s)";
$d || $h and print " $h hour(s)";
$d || $h || $m and print " $m minute(s)";
print " $s second(s)\n";
a5:/pro/3gl/CPAN 105 >

Enjoy, have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Robert Salter
Respected Contributor

Re: grep question

Jeff,

This may or may not help, but a long long time ago in a place far far away there was this group that collected and cataloged experimental Unix tools into a package called "exptools". Some of these commands never made it into the main stream releases of Unix. There was one command named "cgrep", it would allow you to, among other things, cgrep for a pattern and either printout lines before the match, after the match or both. i.e
cgrep +2 abc file1
would give you the line with 'abc' and the next two lines.
cgrep -2 abc file1
would give you the two lines before the match as well as the match.

Th unfortunate thing is exptools is proprietary, unless you're an AT&T or Lucent employee, you can't get them.

The good news is after doing a search on the internet it appears there is a Perl version named apptly cgrep.pl. I haven't tried it so I couldn't say how it works, but I have used and continue to use cgrep and it has been a time saver over having to come up with scripts like the ones listed above, guess I'm basically lazy.

later,

bob
Time to smoke and joke
Leif Halvarsson_2
Honored Contributor

Re: grep question

Hi,
Just a completition to my previous reply. As procura points out my simple awk example don't work if there is repeting lines with the matching pattern. This problem can be solved with a recursive function. Write a small script "test.awk" (it is more readable then writing everything on the command line). Call the script with "awk -f test.awk . Change the matching pattern "DEVICE" to anything you want.

function aaa()
{
getline x
if (x ~ /DEVICE/)
aaa()
else
print x
}

/DEVICE/ { aaa() }
RAC_1
Honored Contributor

Re: grep question

Whay all that when you can do it as follows.

nl file_name|grep "string"
There is no substitute to HARDWORK
Jeff Picton
Regular Advisor

Re: grep question

Hi all

Thanks all, I think i've got enough now to work on my problem.

Jeff
Jamie Harre
Occasional Advisor

Re: grep question

I don't know of a way to do this with grep, but it's easy (if ugly) with awk:

awk '/x/ {getline;print;}' rc.log

So, the single quotes control the shell's treatment of special characters, then the forward slashes around the "x" mean find it. The curly braces are required around a block of executable lines. Having found the line with "x" in it, getline will skip to the next line, and print will print it. Semicolons end the executable line.

Hope that helps.