Re: print line 5 lines previous to comaprison line!
by davorg (Chancellor) on Jun 07, 2001 at 16:51 UTC
|
You don't say what to do if the match is found in the
first five lines of the file. I'm going to assume that this
can't happen. I'm also going to assume that you don't want
to read the whole file into memory at once.
I'd build a buffer that always contains the previous
five lines and work with that. Something like this:
#!/usr/bin/perl -w
use strict;
my @buffer;
push @buffer, scalar <DATA> for 1 .. 5;
my $pat = 8; # adjust to value to search for
while (<DATA>) {
print $buffer[0] if /$pat/;
push @buffer, $_;
shift @buffer;
}
__END__
1
2
3
4
5
6
7
8
9
10
--
<http://www.dave.org.uk>
Perl Training in the UK <http://www.iterative-software.com> | [reply] [d/l] |
|
# change:
print $buffer[0] if /$pat/;
# to:
print $buffer[0] if /\Q$pat\E/o;
The \Q and \E presume that $pat is just a string, not a regex. So you would want to escape any special characters (like '.' or '+' ) and the o tells Perl that $pat isn't going to change in the loop, so it won't keep recompiling the pattern.
| [reply] [d/l] |
Re: print line 5 lines previous to comaprison line!
by tomhukins (Curate) on Jun 07, 2001 at 16:41 UTC
|
my @previous;
while (<LINE>) {
if ($_ eq "STRING TO COMPARE WITH\n") {
print $previous[0];
last;
}
push @previous, $_;
shift @previous if @previous > 5;
}
Update: Thanks to jeroenes for
spotting a couple of things that could be done better - I've
incorporated your suggestions into the code.
Update 2: Thanks to davorg for
noticing that print @previous prints out all
of the last 5 lines, but pat asked for the line 5
lines previous to the one being searched. I've
changed the print @previous line to read
print $previous[0] instead.
| [reply] [d/l] [select] |
|
| [reply] |
Re: print line 5 lines previous to comaprison line!
by Chady (Priest) on Jun 07, 2001 at 16:41 UTC
|
if the file isn't big, read it all in an array, then when you find your match, save your location, and retrieve it directly from the array..
Update:Here it is, completely untested for bugs:
# assuming the file is already opened and has a <IN> filehandle
my @temp;
# and assuming that you won't match before the first 5 lines..
while (my $line = <IN>) {
push @temp, $line;
shift @temp if (scalar @temp > 5);
if ($line =~ /foo/) {
# we've got a match.
print $temp[0];
}
}
Update 2: This looks like davorg's more elegant solution.
He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.
Chady | http://chady.net/ | [reply] [d/l] |
Re: print line 5 lines previous to comaprison line!
by marcink (Monk) on Jun 07, 2001 at 20:57 UTC
|
Hi,
this code seems to do the trick quite effectively:
while (<>) { $a[$i++%6] = $_; print $a[$i%6] if /match/; }
Just change the if condition to something reasonable.
-mk | [reply] [d/l] |
Re: print line 5 lines previous to comaprison line!
by gollem (Acolyte) on Jun 07, 2001 at 16:42 UTC
|
Something like this should work
open X,"<$file";
@rows = <X>;
close X;
for($i=0;$i<$#rows;$i++)
{
if($rows[$i] =~ /something/) {
print $rows[$i-5];
}
}
| [reply] [d/l] |
|
| [reply] |
|
(I cleared this post. Note to self: never post when hungover)
Update:I agree, it's wasteful
| [reply] |
|
when I was opening the file
it would not open as you had written above so I changed to
open (X, $inputfile);
and it opened fine and did what it was meant to do
thanks
but i have seen this before where the syntax you
used to open the file did not
work, have you seen this and any idea why it is so
thanks once again!
Pat ( go raibh mile maith agat)
| [reply] |
Re: print line 5 lines previous to comaprison line!
by DrSax (Sexton) on Jun 07, 2001 at 17:09 UTC
|
As others have said, you can just read the whole file in at once, and then be able to access all elements of the array. If you also want to remove newline characters to make the array easier to process, here is a handy one-liner.
chomp(@myArray = <FILEHANDLE>);
Good luck!
Brian - a.k.a. DrSax | [reply] [d/l] |
|
If file is really huge, you do not want to read whole file into memory. davorg rules!
pmas
| [reply] |