Re: Print Lines above and below string
by jethro (Monsignor) on Aug 10, 2011 at 15:35 UTC
|
Well, if you found examples that print lines before the hit and examples that print lines after the hit, you could just combine them
Usually to print lines before a hit, you create a line storage where the previous 5 lines are stored. When you find the string print the previous lines from storage. To print 5 lines after a hit, just set a counter to 5 when you find it and print lines as long as the counter (that you decrement) is greater than 0. Both methods can be combined without any problems
But the simple algorithms have one drawback: They will reprint lines if these are in the vicinity of two hits. This might be just what you want. If not, use the following method: Have a storage of 5 lines and a counter you set to 10. Always print from the storage, but compare the searchstring with the line you just read. If you get a hit set the counter to 10. Again print and decrement
while ($line = <LOGFILE>) {
push @storage, $line);
if ($line =~ /$string_to_find/i) {
$counter=10;
}
if (@counter-- and @storage>=5) {
print shift @storage;
}
}
Untested
| [reply] [d/l] |
Re: Print Lines above and below string
by thenaz (Beadle) on Aug 10, 2011 at 15:17 UTC
|
So you want the context of the matched string. You will need to keep a rolling window of the last few lines you've seen. Actually, if your input isn't huge, just slurp up into an array, like so (untested):
open LOGFILE, "<$file";
@lines = <LOGFILE>;
for my $i (0..$#lines) {
next unless $lines[$i] =~ /$string_to_find/i;
my $a = $i - 5 < 0 ? 0 : $i - 5;;
my $b = $i + 5 > $#lines ? $#lines : $i + 5;
print $lines[$_i] for my $_i ($a..$b);
}
| [reply] [d/l] |
|
Thanks for the input. Few questions. My file sizes will be around 2.5 megs max. Not sure if that's a problem or not. Also once I ran the script you provided, I got an error on the last line
Here is the error: syntax error at ./readlog5.pl line 12, near "$_i ("
| [reply] |
|
open (LOGFILE, "<$file") or die "Can't open $file";
my @lines = <LOGFILE>;
my $lines; my $i;
for $i(0..$#lines) {
next unless $lines[$i] =~ /$string_to_find/i;
my $a = $i - 5 < 0 ? 0 : $i - 5;;
my $b = $i + 5 > $#lines ? $#lines : $i + 5;
for $i($a..$b) {
print $lines[$i];
}
}
| [reply] [d/l] |
|
what $#lines does?
would anyone please me
| [reply] |
|
| [reply] |
Re: Print Lines above and below string
by Samy_rio (Vicar) on Aug 10, 2011 at 15:17 UTC
|
#!/usr/bin/env perl
use strict;
my $hits=0;
my $string_to_find="string";
my $file = "filename";
open (LOGFILE, $file);
my @cont = <LOGFILE>;
close(LOGFILE);
for(my $i = 0; $i <= $#cont; $i++) {
my $line = $cont[$i];
if ($line =~ /$string_to_find/i) {
my $st;
($i <= 5) ? ($st = 0) : ($st = $i - 5);
my $ln = $i - 1;
my $eln = $i + 1;
my $en = $i + 5;
($en > $#cont) ? ($en = $#cont) : ();
print @cont[$st..$ln];
print $line;
print @cont[$eln..$en];
}
}
Regards, Velusamy R. eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';
| [reply] [d/l] [select] |
|
| [reply] |
Re: Print Lines above and below string
by Gulliver (Monk) on Aug 10, 2011 at 15:26 UTC
|
| [reply] |
Re: Print Lines above and below string
by duyet (Friar) on Aug 10, 2011 at 15:14 UTC
|
On the command line: grep -n5 "search_string" filename
If you want to use it in your code
my $result = `/usr/bin/grep -n5 "search_string" $file`;
print $result;
| [reply] [d/l] [select] |
|
| [reply] |
|
Sorry i first thought you wanted to print empty lines. Try the "grep" command, as in my updated post
| [reply] |