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 Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Capture lines above and below an expression match 1

Status
Not open for further replies.

swabs

IS-IT--Management
Jul 28, 2003
155
US
Hello,
I am trying to capture relevant data from the output of a cmd.
the data I will get in a log is similar to the info below:

JOHNRV3000

Computer Group Policy processing cycle:
STARTED: 13:51:59 on 9/9/2005
FINISHED: 13:52:4 on 9/9/2005
Total elapsed processing time: 0 hours, 0 minutes, 4 seconds and 500 msec.

User Account: jtech Group Policy processing cycle:
STARTED: 14:26:49 on 7/29/2004
FINISHED: 14:26:49 on 7/29/2004
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 0 msec.

User Account: Administrator Group Policy processing cycle:
STARTED: 15:41:27 on 11/9/2004
FINISHED: 15:41:27 on 11/9/2004
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 265 msec.

User Account: johnrv Group Policy processing cycle:
STARTED: 14:49:4 on 9/9/2005
FINISHED: 14:49:4 on 9/9/2005
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 641 msec.

I would like to open the file and have it match the pattern:
Computer Group Policy processing cycle:, if it matches that pattern I want the script to capture the 3 previous lines, the line itself and the 4 following lines. Here is what I have so far:-->

opendir(DIRHANDLE,".");
@filenames = readdir(DIRHANDLE);
@results;


############################################################################
##opens file and parses for pertinent information
open (Daily, "$filenames[3]") || die "Couldn't open file\n";

while (<Daily>) {

foreach ($_) {
if (m/Computer Group Policy processing cycle:/) { SOMEHOW GET PREVIOUS 3 LINES ETC}
}



}


Any help sorting this out would be greatly appreciated.

thanks,
Ben Svobodny
 
What platform? Windoze by any chance?
If you have linux available you could use grep since it has "--before" and "--after" switches that you can feed with line counts to get the desired effect.


Trojan.
 
Indeed I am in a Windoze environment, but I will try installing cygwin and running it through there.

How would that grep command look?

if (m/Computer Group Policy processing cycle:/) { gprep $_ -b 3 -A 4}
}


thanks,
Ben
 
used another line for match - for obvious reasons:-

Code:
[b]#!/usr/bin/perl[/b]

@lines = <DATA>;

for ($x=0; $x<=$#lines; $x++) {
  if ($lines[$x] =~ 'jtech Group Policy processing cycle') {
    for ($y=-3; $y<=4; $y++) {
      print "$y : " . $lines[$y];
    }
  }
}

__DATA__
JOHNRV3000  

Computer Group Policy processing cycle: 
STARTED: 13:51:59 on 9/9/2005
FINISHED: 13:52:4 on 9/9/2005
Total elapsed processing time: 0 hours, 0 minutes, 4 seconds and 500 msec.

User Account: jtech Group Policy processing cycle: 
STARTED: 14:26:49 on 7/29/2004
FINISHED: 14:26:49 on 7/29/2004
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 0 msec.

User Account: Administrator Group Policy processing cycle: 
STARTED: 15:41:27 on 11/9/2004
FINISHED: 15:41:27 on 11/9/2004
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 265 msec.

User Account: johnrv Group Policy processing cycle: 
STARTED: 14:49:4 on 9/9/2005
FINISHED: 14:49:4 on 9/9/2005
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 641 msec.

outputs:-

Code:
-3 : STARTED: 14:49:4 on 9/9/2005
-2 : FINISHED: 14:49:4 on 9/9/2005
-1 : Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 641 msec.0 : JOHNRV3000  
1 : 
2 : Computer Group Policy processing cycle: 
3 : STARTED: 13:51:59 on 9/9/2005
4 : FINISHED: 13:52:4 on 9/9/2005


Kind Regards
Duncan
 
If you don't want to read the whole file into memory at once:
Code:
#!/usr/bin/perl -w
use strict;
my @buffer = ("","",""); # Three line buffer
my $count = 0;
while(<DATA>) {
  # Check for match
  if(m/jtech Group Policy processing cycle:/) {
    print @buffer;
    $count = 5;   # Extra lines + 1 to allow for this line
  }
  # Buffer the current record
  push @buffer, $_; shift @buffer;
  # Handle match line output and next 4 lines
  if($count) {
    print $_;
    $count--;
  }
}
__DATA__

JOHNRV3000  

Computer Group Policy processing cycle:
STARTED: 13:51:59 on 9/9/2005
FINISHED: 13:52:4 on 9/9/2005
Total elapsed processing time: 0 hours, 0 minutes, 4 seconds and 500 msec.

User Account: jtech Group Policy processing cycle:
STARTED: 14:26:49 on 7/29/2004
FINISHED: 14:26:49 on 7/29/2004
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 0 msec.

User Account: Administrator Group Policy processing cycle:
STARTED: 15:41:27 on 11/9/2004
FINISHED: 15:41:27 on 11/9/2004
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 265 msec.

User Account: johnrv Group Policy processing cycle:
STARTED: 14:49:4 on 9/9/2005
FINISHED: 14:49:4 on 9/9/2005
Total elapsed processing time: 0 hours, 0 minutes, 0 seconds and 641 msec.
Duncdude's code will undoubtedly be faster but mine is not limited by memory at all. It will work on any length file.

Duncdude: Watch your regex syntax my friend. If you want to use apostrophes as regex delimiters you should really prefix the regex with an "m".
Code:
if ($lines[$x] =~ [red]m[/red]'jtech Group Policy processing cycle') {
Otherwise, stick with the forward slash chararcter:
Code:
if ($lines[$x] =~ [red]/[/red]jtech Group Policy processing cycle[red]/[/red]) {

:)

Trojan.
 
Hi Trojan

Blimey! I hope you know me better than that!!! That was because i started with eq as i was gonna use Computer Group Policy processing cycle: ... then realised there was almost nothing before this line. When i changed it to a latter line i changed to a regex and completely forgot to change the syntax. Thanks for picking it up though. Pretty daft of me!

By some odd fluke though - i did test run it... and it works!? Now i don't understand that!


Kind Regards
Duncan
 
Here's a slightly different way:
Code:
my ($lines_before, $lines_after, @lines) = (3,4,'');
my $pattern = 'Computer Group Policy processing cycle:';
foreach (1..($lines_after+$lines_after)) { push @lines, scalar <DATA>; }
while (! eof(DATA)) {
    if (index($lines[$lines_before],$pattern,0) != $[ - 1) { print @lines; };
    shift @lines; push @lines, scalar <DATA>;
}
 
I was just nudging you a little duncdude.
You'll forgive me for that little tease, I'm sure.
You can't blame me though!
;-)

rhash, nice and condensed, if not quite so readable.
:)


Trojan.
 
Of course i don't mind... I just thought for a moment that you guessed i intended to do that!!! I am no Perl master but i'm not that daft! I left myself wide open for that tease eh!? And where has my lovely motorbike weather gone? I might be on this forum more often now...


Kind Regards
Duncan
 
I have noticed before that you can often get away quotes instead of delimiters. I do worry though that later versions will not allow this.
Although I was taking a somewhat "tongue-in-cheek" shot at you, in all seriousness it's important to raise the issue since others might blindly copy it and see it work fine and consider that it is the norm. Obviously issues like that need to be highlighted and I would expect you to do the same to me (just not too much teasing eh? ;-) ).
It's a shame the weather has failed for you, it's fine with me so if you don't need the bike for a while, I know someone that would take good care of it for you! ;-)


Trojan.
 
another way using Tie::File:

Code:
#!perl -w
use strict;
use Tie::File;

opendir(DIR,".") or die "$!";
my @filenames = readdir(DIR);
close(DIR);  
my @results = ();
tie my @data, 'Tie::File', $filename[3] or die "$!";

($data[$_] =~ /Computer Group Policy processing cycle:/ ?
push @results, @data[$_-3 .. $_+4] :
next) for (0..$#data);

print "$_\n" for @results;

although I find the minus 3 and plus 4 lines confusing based on the sample data file lines you posted.
 
thanks very much for your help.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top