fatfinger has asked for the wisdom of the Perl Monks concerning the following question:

Good Day,
I'm new to perl and I basically write simple perl scripts to format and manipulate text files.
My script as is:

I open a textfile located on my windows file system and read in the text file lines. Script currently looks for a line within test.txt that contains a user's text input (see script below) and prints only that line. My problem:

Now the user wants to see the line of text above and the line of text below $input. Any ideas how I could enhance the script below to do this. A quick example:
If document (test.txt) contains:

fff
aaa
bbb
ccc
ddd

if user types in "bbb" I need to capture

aaa
bbb
ccc

Thanks everyone for your time and perl help.

Script as is:
########################################################### open(FILE, "<C:\\FolderA\\test.txt")or die("Can't find file name at $F +ILE"); #Get user input print"Please type the term you're looking for\n"; $input=<STDIN>; chomp $input; #Read in lines of text file while ($lines=<FILE>) { chomp ($lines); $cnt++; #Find any lines within the text file that contain user input ($input) + and print them. if($lines=~/$input/i) { print"$lines\n"; } } close(FILE); ###########################################################

Replies are listed 'Best First'.
Re: Extracting Lines of a text file
by graff (Chancellor) on Nov 04, 2008 at 01:14 UTC
    I suppose I'd do it like this;
    #!/usr/bin/perl use strict; use warnings; my $filename = "C:/FolderA/test.txt"; # default input file if ( @ARGV > 1 and -f $ARGV[1] ) { $filename = pop; # alternatively, get input file from command lin +e } my $pattern; if ( @ARGV ) { $pattern = shift; # get search pattern from command line } else { die "Usage: $0 search_pattern_regex [input.filename]\n"; } open( FILE, "<", $filename ) or die "Open failed on $filename: $!"; my @line_buffer; while (<FILE>) { push @line_buffer, $_; shift @line_buffer if ( @line_buffer > 3 ); print join( "", @line_buffer, "\n" ) if ( @line_buffer > 1 and $line_buffer[-2] =~ /$pattern/ ); } print join( "", @line_buffer ) if ( $line_buffer[-1] =~ /$pattern/ ); close FILE;
    Some points to consider:
    • How do you want to handle the case where two consecutive lines match the pattern?
    • Do you want to enable or disable the use of regex magic characters in the user-supplied pattern?
    • Do you want to parameterize the number of lines of context to include in the output for each match (providing a command line option to control this)?
    Note that the gnu "grep" tool (available for windows via cygwin and other "unix-utils-for-windows" packages) already does what you are trying to do here, so unless there's some perlish capability you want to add that the standard gnu grep doesn't have, there's no need to reinvent this wheel.
Re: Extracting Lines of a text file
by apl (Monsignor) on Nov 04, 2008 at 01:09 UTC
    If you were doing this by hand, how would you answer your question? Keep in mind you'd have to remember the previous line you'd read, and you'd also have to remember if the previous line had matched the specified input.

    If you can write out the steps, you can write the code.

Re: Extracting Lines of a text file
by ikegami (Patriarch) on Nov 04, 2008 at 10:42 UTC

    What if the you have

    aaa bbb ccc ddd ccc eee fff
    and you search for "ccc". Do you want
    bbb ccc ddd ccc eee

    or

    bbb ccc ddd ddd ccc eee

    or something else?

    Also, is the input a text string or a regex pattern. You imply it's the former ("term"), but treat it as the latter (/$input/ instead of /\Q$input\E/).

      ... sh..., you are right, my mistake!
Re: Extracting Lines of a text file
by baxy77bax (Deacon) on Nov 04, 2008 at 10:16 UTC
    hi,

    i don't know if this helps but you could play around with regex and do some thing like this :

    use strict; print"Please type the term you're looking for\n"; chomp (my $cho = <STDIN>); open (FILE, "<", $ARGV[0]) || die "$!"; $/ ="(.*)\n(.*)\n(.*)"; while (<FILE>){ m/(.*)\n(.*)\n(.*)/gi; next if (!m/(.*)\n$cho\n(.*)/ ); print "$1\n$cho\n$2"; } $/ = "\n";
    it does exactly this:

    fff aaa aaa bbb => bbb ccc ccc ddd
    there are many ways to do it ! but it depends if this is what you actually need. here i've just changed the recognition pattern (input record separator) from \n (which is standard) to stuff\nyour_stuff\nstuff and then evaluate the middle pattern to your pattern. read more about $/ here.

      That doesn't work like you think it does. You should head your own advice and read the docs for $/. $/ is treated as a string, not a regexp pattern. Try it with the file

      fff aaa bbb ccc ddd fff aaa bbb ccc ddd
Re: Extracting Lines of a text file
by sanku (Beadle) on Nov 04, 2008 at 11:41 UTC
    hi try out this one
    #!/usr/bin/perl use strict; print "Enter the txt\n"; my ($input,@ss,$i); chop($input=<STDIN>); open(FILE,"txt.txt") or die $!; @ss=<FILE>; close(FILE); foreach $i(0 .. scalar @ss){ if($ss[$i] =~ /$input/) { if($i ne 0){print "$ss[$i-1]";} print "$ss[$i]"; print "$ss[$i+1]"; } }