Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

how to add more intelligence to grep functionality

by jesuashok (Curate)
on Jan 11, 2006 at 18:57 UTC ( #522527=perlquestion: print w/ replies, xml ) Need Help??
jesuashok has asked for the wisdom of the Perl Monks concerning the following question:

Hi Gr8 People

#!/usr/local/bin/perl use strict; + my @array = ( 'account_trend','trend_report','revenuebytrafficker','ti +cketstatus','lostinventory','campaigndetail','campaignsummary','packa +gesummary','placementsummary','bookedbyaccount','bookedbysalesperson' +,'accounttrends','salespersontrends','salessitetrend','placementperfo +rmance','packageperformance','forcastsummary'); + my $value = 'reve*ker'; + foreach (@array) { if ( grep (/$value/,$_) ) { print "Matched :$_:\n"; } } +
In the above the how to acheive the following to be matched using grep

If $value = "accoun*end" then output should be

Matched :account_trend Matched :accounttrends

"Keep pouring your ideas"

Comment on how to add more intelligence to grep functionality
Download Code
Re: how to add more intelligence to grep functionality
by mrborisguy (Hermit) on Jan 11, 2006 at 19:06 UTC
    @new = grep /accoun.*end/, @array; print "Matched :$_:\n" for @new;

    Notice the .*. The period means any character, the asterisk means any amount of these. Compare that to accoun*end which mean "find 'accou', then any amount of n's, then 'end'."

        -Bryan

Re: how to add more intelligence to grep functionality
by japhy (Canon) on Jan 11, 2006 at 19:07 UTC
    What you mean to ask is, "How do I convert a glob-style regex to a Perl regex?" The Text::Glob module helps here.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: how to add more intelligence to grep functionality
by holli (Monsignor) on Jan 11, 2006 at 19:33 UTC
    hand rolled solution:
    #!/usr/local/bin/perl use strict; my @array = ( 'account_trend', 'trend_report', 'revenuebytrafficker', 'ticketstatus', 'lostinventory', 'campaigndetail', 'campaignsummary', 'packagesummary', 'placementsummary', 'bookedbyaccount', 'bookedbysalesperson', 'accounttrends', 'salespersontrends', 'salessitetrend', 'placementperformance', 'packageperformance', 'forcastsummary' ); my @values = ( '??m*', 'reve*ker', 'accoun*end', ); for ( @values ) { print "mask: $_\n"; my $regex = mask2re ($_); print "re $regex\n"; print join ("\n", grep { /$regex/ } @array), "\n\n"; } #turns a simple mask into a regex where * means #none ore more chars amd ? means exactly one char sub mask2re { #replacements (after quotemeta) my %map = ( "\\*" => ".*?", "\\?" => ".", ); #quotema everything my $re = quotemeta ($_[0]); #replace * and ? by regex active statements $re =~ s/(\\[\*|\?])/$map{$1}/g; #return compiled regex return qr/^$re/; }
    Output:
    mask: ??m* re (?-xism:^..m.*?) campaigndetail campaignsummary mask: reve*ker re (?-xism:^reve.*?ker) revenuebytrafficker mask: accoun*end re (?-xism:^accoun.*?end) account_trend accounttrends


    holli, /regexed monk/
Re: how to add more intelligence to grep functionality
by GrandFather (Cardinal) on Jan 11, 2006 at 19:42 UTC

    You have your answer, but for future reference your node would have been better if you trimmed the number of items in the array to show just enough cases to make your problem clear, and if your question matched the actual example in the code.

    As it stands most browsers will either break your nasty long line in a random place, or not break it at all meaning that a huge amount of scrolling is required to read your node and its replies. Even replying in such a case is a real pain in the butt because the edit box is extreamly wide.

    Cleaned up (and fixed) code could look like this:

    use strict; use warnings; my @array = ('account_trend', 'trend_report', 'revenuebytrafficker'); my $value = qr'reve.*ker'; foreach (@array) { print "Matched :$_:\n" if /$value/; }

    Prints:

    Matched :revenuebytrafficker:

    It's not clear to me why you had a grep in there. A version using grep is:

    use strict; use warnings; my @array = qw(trend_report revenuebytrafficker revengebysmoker); my $value = qr'reve.*ker'; my @matches = grep {/$value/} @array; print ("Matched :" . (join ": :", @matches) . ":\n") if @matches;

    Prints:

    Matched :revenuebytrafficker: :revengebysmoker:

    DWIM is Perl's answer to Gödel

      GrandFather gave you an example of how to make your code work, but I think a reference is in order (no, not that kind).

      Instead of my $value = 'reve*ker';, as in your original code, GrandFather changed it to my $value = qr'reve.*ker';. See that little qr in there? That's the quote regex operator. It takes a string, compiles it into a regex, and returns it for later use. To quote perlop,

      This operator quotes (and possibly compiles) its STRING as a regular expression. STRING is interpolated the same way as PATTERN in m/PATTERN/. If "'" is used as the delimiter, no interpolation is done. Returns a Perl value which may be used instead of the corresponding /STRING/imosx expression.

      perlop. Lots of good stuff in there.

      HTH

      BTW, I'd like to second GrandFather's comment about long lines. Horizontal scrolling is awkward.

Re: how to add more intelligence to grep functionality
by blazar (Canon) on Jan 12, 2006 at 11:28 UTC

    You already received a lot of replies. The common consensus seems to be that you just mistook shell patterns for regular expressions. It seems to me that no one has stressed enough that you seem to have a poor understanding of grep: it is made for grepping across lists, and indeed you can pass it a list of exactly one element - only, you generally just don't want to! So you either want:

    my @matching elements=grep /$wahtever/, @array; print $_, "\n" for @matching elements; # But then just: # print $_, "\n" for grep /$wahtever/, @array; # if you don't need @matching elements elsewhere

    or

    foreach (@array) { print "Matched :$_:\n" if /$value/; }

    or even

    /$value/ and print "Matched :$_:\n" for @array;

    But then I have the feeling that you really wanted to ask about something different, since in all earnestness I couldn't make 100% sense of your wording.

    Incidentally, to define that long list of "words", you may use use qw// to great advantage, improving readability, typing speed and possibly reducing the risk of typos.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://522527]
Approved by mrborisguy
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (8)
As of 2014-12-21 05:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (103 votes), past polls