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

Hi all

I am using grep function and grepping few characters from a file.Now i want to print the entire line in the file which has the characters that matched.

open(FILE,"$filepath") or die "Couldn't open file for writing: $!";

$error1=(grep {/0 Items in Feed & 0 New Fetched items/} <FILE>);

if($error1) { print "match found"; } else { print"nothing"; }

close FILE;

Now in the above after getting match,i want to print the entire line in which i found the match and grepped

can anyone help me with this

Replies are listed 'Best First'.
Re: printing the line after grepping
by moritz (Cardinal) on Nov 11, 2009 at 14:05 UTC
    use strict; use warnings; use autodie qw(open close); ... open my $handle, '<', $filepath; while (<$handle>) { print if /0 Items in Feed & 0 New Fetched items/; } close $handle;
    Perl 6 - links to (nearly) everything that is Perl 6.

      A beginner's version of that would be:

      use strict; use warnings; use 5.010; my $pattern = '0 Items in Feed & 0 New Fetched items'; open(my $INFILE, "<", "data2.txt") or die "There was a problem: $!"; while (my $line = <$INFILE>) { print $line if $line =~ /$pattern/; }

      If you write the while loop like this:

      while (<$INFILE>) { }

      it becomes magical in perl. Every time through the while loop, the next line from the file will be read into a variable named $_. Calling print with no arguments will print $_, and a regex will match against $_ by default.

        Actually, while (my $line = <$INFILE>) is equally magical.
        while (<$INFILE>) => while (defined($_ = <$INFILE>) while (my $line = <$INFILE>) => while (defined(my $line = <$INFILE>)
Re: printing the line after grepping
by happy.barney (Friar) on Nov 11, 2009 at 13:56 UTC
    @error1=(grep {/0 Items in Feed & 0 New Fetched items/} <FILE>); if(@error1) { print "match found (@error1)"; } else { print"nothing"; +}
    this approach is quite dangerous, as it reads whole FILE before grep-ing. Try to use while
      thats fine..but how do i print the line where the characters i grepped was found.I am new to perl scripting
        That's what the code he posted does!?
        oh yeah..!!!thank u so much
Re: printing the line after grepping
by johngg (Canon) on Nov 11, 2009 at 14:06 UTC

    Make the LHS an array and grep the line you want then print it.

    $ cat > tfile line1 line2 line3 $ perl -Mstrict -we ' > my @error1 = do > { > open my $fh, q{<}, q{tfile} or die $!; > grep m{2}, <$fh>; > }; > print @error1 ? qq{match found : @error1} : qq{nothing\n};' match found : line2 $ cat > tfile line1 line3 $ $ perl -Mstrict -we ' > my @error1 = do > { > open my $fh, q{<}, q{tfile} or die $!; > grep m{2}, <$fh>; > }; > print @error1 ? qq{match found : @error1} : qq{nothing\n};' nothing $

    I hope this is helpful.

    Cheers,

    JohnGG

Re: printing the line after grepping
by ack (Deacon) on Nov 11, 2009 at 17:44 UTC

    If you change from the scalar context of grep to the list context, it'll capture the lines that match and then you can print out the list of matching lines.

    The codes would look something like this:

    open(FILE,"<",$filepath) or die "Couldn't open file for writing: $!"; @error1 = grep { /0 Items in Feed & 0 New Fetched Items/ } <FILE>; if(scalar(@error1)>0) { print "match found\n"; print "@error1"; } else { print "nothing"; } close FILE;

    I tried the above snippet on a test file and it works like I believe you are hoping.

    Note several things. First, I find that it is generally a good idea to use the 3-argument form of the open as I did in the above.

    Second, since the code is storing the lines returned by grep into a list, it is easy to see if any lines matched simply by checking the number of entries in the list (i.e., by using if(scalar(@error)>0){...more code...}. It is, of course equally valid to use if(@error1 > 0){...more code...} since the if() forces @error1 into scalar context so that it directly returns the number of elements in it. I prefer (just my own preference) to explicitly use the scalar() function to remind me that I'm looking for the number of elements in the list.

    Third, I do print "@error1" under the assumption (as reflected in my code snippet and in yours) that the lines already contain a "new line" character (i.e., "\n") at the end of each line). I make that assumption because there is no chomp() after reading in the lines (you could add chomp; into the block code in your grep before the reqex match). Given that they already contain the new line, then just doing a <c>print "@error1" will result in output that is already line separated.

    Finally, I much prefer the other responders' suggestions to use while() rather than grep() so that you only read one line at a time into your space. grep(), as others wisely note, first slurps the entire file into your working space as a list and then operates on that list. Using the while() construct only works with one line at a time which is much more conservative of work space. Of course, if your FILE is not very big then the grep() may be a little more succinct and compact. But, from my perspective, that's for you to decide.

    I hope this helps.

    ack Albuquerque, NM

      since the if() forces @error1 into scalar context

      No. Operators only impose context on their operands, and @error1 is not if's operand. if imposes a scalar context on > (which does nothing since > always returns a scalar).

      On the other hand, @error1 is an operand of >, and > imposes a scalar context on its operands.

      I prefer to explicitly use the scalar() function to remind me that I'm looking for the number of elements in the list.

      First of all, you're wrong about scalar returning the number of elements in a list.

      >perl -le"print join ',', 5,6,7" 5,6,7 >perl -le"print join ',', scalar(5,6,7)" 7 <--- Not 3 >perl -le"print join ',', localtime" 13,2,13,11,10,109,3,314,0 >perl -le"print join ',', scalar(localtime)" Wed Nov 11 13:02:26 2009 <--- Not 9

      Don't confuse array for list.

      I prefer to explicitly use the scalar() function to remind me that I'm looking for the number of elements in the [array].

      If that's true, you'd be better off using 0+@error1. It's much better at indicating you want a number of elements.

      But really, doesn't > 0 already indicate you're dealing with a number?!