Peeter Joot's (OLD) Blog.

Math, physics, perl, and programming obscurity.

grep with a range using a perl one liner.

Posted by peeterjoot on September 23, 2009

Here’s a small shell scripting problem. I have grep output that I’d like further filtered

# ./displayInfo | grep peeterj
Offline RG:blah_peeterj_0-rg
Offline RG:blah_peeterj_0-rg_MLN-rg
Offline RG:idle_peeterj_998_goo-rg
Offline RG:primary_peeterj_900-rg
Online Equivalency:blah_peeterj_0-rg_MLN-rg_group-equ
...
MORE STUFF I DON'T CARE ABOUT.
...
Online Equivalency:instancehost_peeterj-equ
        '- Online APP:instancehost_peeterj_goo:goo
Online Equivalency:primary_peeterj_900-rg_group-equ

peeterj is my userid and the command in question that generates this has output for all the other userids on the system. I’m only interested in the subset of the info that has my name, hence the grep.

However, once the text Equivalency is displayed I’m not interested in any more of it. I could filter out all the patterns that I’m also not interested in doing something like:

# ./displayInfo | grep peeterj | grep -v -e Equivalency -e instancehost -e ...

but this is a bit cumbersome. An alternative is filtering specifically on what I want

# ./displayInfo | grep -e 'peeterj.*blah' -e 'peeterj.*idle' -e 'primary_peeterj' -e ...

but that also means I have to know and enumerate all such expressions for what I’m interested in. Since I’m on Linux my grep is gnu-grep, so I considered using ‘grep -B N’ to show N lines of text precededing a match, but this also outputs the text I’m not interested in so doesn’t really work.

Here’s what I came up with (I’m sure there’s lot of ways, some perhaps easier, but I liked this one). It uses the perl filtering option -n once again, to convert the entire script into a filter (specified here inline with -e instead of in a file) :

# ./displayInfo | perl -n -e 'next unless (/$ENV{USER}/) ; last if ( /Equivalency/ ) ; print ;'

Basically, this one liner is as if I’d written the following perl script to read and process all of STDIN:

#/usr/bin/perl

while (<>)
{
   my $line = $_ ;
   next unless ($line =~ /$ENV{USER}/) ; # "grep" for my userid (peeterj).

   # Won't get here until I've started seeing the peeterj text.
   last if ( $line =~ /Equivalency/ ) ;         # stop when I've seen enough.

   # If I get this far print the "matched" line as is:
   print $line ;
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: