Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Can figure out a way to get File::Grep's fgrep to chomp matches

by Lady_Aleena (Curate)
on May 13, 2017 at 23:36 UTC ( #1190241=perlquestion: print w/replies, xml ) Need Help??
Lady_Aleena has asked for the wisdom of the Perl Monks concerning the following question:

Hello. I've been stuck for over an hour now. I can't figure out how to get File::Grep's fgrep to return chomped values in its matches. I've tried chomping $file, chomping $_ in the fgrep, and more. Am I using it wrong, not understand something in the module description, or just plain out of luck and have to munge the values of matches later?

#!/usr/bin/perl use strict; use warnings; use File::Grep qw(fgrep); use Data::Dumper; my @line = fgrep { /^[2-6] .+$/ } *DATA; print Dumper(\@line); __DATA__ 2 foo 3 bar 4 baz 5 qux 6 quux 7 thingy 8 widget

The output is

$VAR1 = [ { 'filename' => *::DATA, 'count' => 5, 'matches' => { '1' => '2 foo ', '2' => '3 bar ', '3' => '4 baz ', '4' => '5 qux ', '5' => '6 quux ' } } ];

I'm at the end of my abilities.

No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
Lady Aleena

Replies are listed 'Best First'.
Re: Can figure out a way to get File::Grep's fgrep to chomp matches
by haukex (Abbot) on May 14, 2017 at 08:45 UTC

    The File::Grep documentation for fgrep says "While you can change $_ if necessary, only the original value of the line will be added to the returned list", so if you really want to use this module you'll have to use one of the workarounds presented by the monks here.

    However, the doc also says "File::Grep mimics the functionality of the grep function in perl", which is contradictory since in Perl's grep, modifying $_ does modify the original value. Despite Perl's own documentation saying "This is usually something to be avoided when writing clear code", I'd still argue that if fgrep is supposed to be like grep, it should emulate this behavior too. Even though a look at the source doesn't show any serious problems, personally I probably wouldn't use this module for two additional reasons: it doesn't report any errors by default (and even when they're enabled they're only warnings) and it doesn't allow the setting of open modes like :crlf or :utf8.

    I'd probably just go with a good old while(<$fh>) loop.

    for my $file (@files) { open my $fh, '<', $file or die "$file: $!"; while (<$fh>) { /^[2-6] .+$/ or next; chomp; push @results, $_; } close $fh; }

    Update: Punctuation.

      Furthermore it wasn't maintained for a decade and has a random interface.
      • fmap and fgrep only accept filenames on the RHS, hence they can't be chained.
      • The returned data structure is different in both cases. fgrep a AoH and fmap an array.
      At least that's what I read from the POD and LA's posts.

      I'd call this experimental abandonware.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

Re: Can figure out a way to get File::Grep's fgrep to chomp matches
by kcott (Chancellor) on May 14, 2017 at 06:02 UTC

    G'day Lady Aleena,

    I haven't used that module before, so there may be a better way of doing this; however, the following achieves what you appear to want.

    #!/usr/bin/env perl use strict; use warnings; use File::Grep qw(fgrep); use Data::Dumper; my @line = map { chomp $_ for values %{$_->{matches}}; $_ } fgrep { /^ +[2-6] .+$/ } *DATA; print Dumper(\@line); __DATA__ 2 foo 3 bar 4 baz 5 qux 6 quux 7 thingy 8 widget

    Output:

    $VAR1 = [ { 'count' => 5, 'matches' => { '3' => '4 baz', '4' => '5 qux', '1' => '2 foo', '5' => '6 quux', '2' => '3 bar' }, 'filename' => *::DATA } ];

    — Ken

Re: Can figure out a way to get File::Grep's fgrep to chomp matches
by LanX (Bishop) on May 13, 2017 at 23:45 UTC
    I did a text search for chomp in File::Grep and found this example in the synopsis

     fmap { chomp; lc; }  

    hence there is no other way than doing the obvious

    my @line = map { chomp }  fgrep { /^[2-6] .+$/ } *DATA;

    This should do too

    my @line = grep { /^[2-6] .+$/ } fmap {chomp} *DATA;

    HTH

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

    update

    The usual trick to include the grep condition into map is left as exercise. ;)

      Thanks for trying, but here are the results of both directions:

      my @line = map { chomp }  fgrep { /^[2-6] .+$/ } *DATA;

      $VAR1 = [ 0 ];

      my @line = grep { /^[2-6] .+$/ } fmap {chomp} *DATA;

      $VAR1 = [];

      It is okay if it is not possible until later munging. It is just a tad annoying.

      No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
      Lady Aleena

        chomp doesn’t return quite like that. This should work–

        my @line = map { chomp; $_ } fgrep { /^[2-6] .+$/ } *DATA;

        But maybe this is better–

        chomp( my @line = fgrep { /^[2-6] .+$/ } *DATA );
        I see, please try

          my @line = fmap { chomp; /^[2-6] .+$/ ? $_ : () } *DATA;  

        Sorry, I don't think this interface was well designed ...

        HTH :)

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1190241]
Approved by beech
Front-paged by beech
help
Chatterbox?
[sierpinski]: thanks LanX that helps
[haukex]: the first index is always 0 - $#array gives you the last index in @array
[sierpinski]: gotcha, thanks
[LanX]: length = last index +1

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (16)
As of 2017-12-13 16:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What programming language do you hate the most?




















    Results (369 votes). Check out past polls.

    Notices?