A question about regex

  • Thread starter Madhusudhanan Chandrasekaran
  • Start date
M

Madhusudhanan Chandrasekaran

Hi,

I am a perl newbie. I am reading from a file line by line and
matching it for a partiuclar regex. If the match is found, I want
to print the previous and the next few lines.

i.e. if the lines of the file are:

This is a
String
But I do not
know how to
print it


and if my pattern is "But I do not", I would like to print as
"String But I do not know how to". Here it prints out the previous
and the next line, keeping it variable is desired.

Thanks in advance,
_Madhu
 
P

Paul Lalli

I am a perl newbie. I am reading from a file line by line and
matching it for a partiuclar regex. If the match is found, I want
to print the previous and the next few lines.

i.e. if the lines of the file are:

This is a
String
But I do not
know how to
print it

and if my pattern is "But I do not", I would like to print as
"String But I do not know how to".

Show what you've done so far, and someone can help you out.

Also, have you checked the FAQ?
$ perldoc -q "more than one line"
Found in /software/perl-5.8.5-0/pkg/lib/5.8.5/pod/perlfaq6.pod
I'm having trouble matching over more than one line. What's
wrong?

In general, if you're processing line-by-line like you say you are,
there is no particular regexp that's going to help you. As you read
through each line, save the current line in some variable, then when
you find your match, print that variable you saved, print the current
line, and read and print once more.

Paul Lalli
 
J

Jürgen Exner

Madhusudhanan said:
I am a perl newbie. I am reading from a file line by line and
matching it for a partiuclar regex. If the match is found, I want
to print the previous and the next few lines.

Nothing to do with Perl or REs but rather with basic algorithm design.
Because you are reading the file line by line and you can only detect the
desired line _after_ working on the next one already you need to keep a
history of one line, something like $previous_line which you update every
single time you read a new line.

Adding the following lines, too, is not a big deal. Just read and print them
when your condition is true.

jue
 
T

Tad McClellan

I am a perl newbie. I am reading from a file line by line and
matching it for a partiuclar regex. If the match is found, I want
to print the previous and the next few lines.

i.e. if the lines of the file are:

This is a
String
But I do not
know how to
print it


and if my pattern is "But I do not", I would like to print as
"String But I do not know how to". Here it prints out the previous
and the next line, keeping it variable is desired.


--------------------------------
#!/usr/bin/perl
use warnings;
use strict;
use Tie::File;

tie my @array, 'Tie::File', 'file' or die "could not tie 'file' $!";
my $prev = 1;
my $next = 1;

foreach my $i ( 0 .. $#array ) {
next unless $array[$i] =~ /^But I do not$/;
print "@array[ $i-$prev .. $i+$next ]\n";
}
 
H

Henry Law

Madhusudhanan said:
Hi,

I am a perl newbie. I am reading from a file line by line and
matching it for a partiuclar regex. If the match is found, I want
to print the previous and the next few lines.

I'm all for using Perl, but if you're on a UNIX system then grep -A1 -a1
would do this. (Might even work on another OS with a grep port).
 
A

anno4000

Tad McClellan said:
I am a perl newbie. I am reading from a file line by line and
matching it for a partiuclar regex. If the match is found, I want
to print the previous and the next few lines.

i.e. if the lines of the file are:

This is a
String
But I do not
know how to
print it


and if my pattern is "But I do not", I would like to print as
"String But I do not know how to". Here it prints out the previous
and the next line, keeping it variable is desired.


--------------------------------
#!/usr/bin/perl
use warnings;
use strict;
use Tie::File;

tie my @array, 'Tie::File', 'file' or die "could not tie 'file' $!";
my $prev = 1;
my $next = 1;

foreach my $i ( 0 .. $#array ) {
next unless $array[$i] =~ /^But I do not$/;
print "@array[ $i-$prev .. $i+$next ]\n";
}

Ah, that's a good use of Tie::File. It hides the complexities of treating
a file as an array of lines (which you want to do for that problem) without
worrying about slurping the entire file.

It is still not perfect. When the next line is "But I do not" again,
it starts another triplet that partially overlaps with the one already
printed.

There are also no provisions in case the very first (or last) line is
a match, in which cases $i-$prev or $i+$next may leave the range of
defined lines.

One solution would be to collect indices of lines to print in an array
(@print_these) and use a hash (%seen) to detect duplicates. After the
loop, negative indices can be shifted off @print_these, and indices
beyond $#array can be popped. Finally, @array[ @print_these] can be
output.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top