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

Hi,

After reading the 'worst nodes' I decided to post this.

I am trying to extract the value from a 'param=value' list, using grep. It did not work.

Basically I am trying to do this and it does not work.

perl -e'print grep /param=(.*)/, "param=value";'

I promptly get 'param=value' as the response, while I am expecting to get 'value'.

How do I accomplish this?

Thanks in advance

Replies are listed 'Best First'.
Re: grep question
by Roy Johnson (Monsignor) on May 26, 2005 at 21:53 UTC
    I think your confusion is in what tool extracts from what. grep extracts elements from a list; regex capture extracts pieces from a string. You're using both in your example, when you only need to use a regex: perl -e 'print "param=value" =~ /param=(.*)/' On the plus side, at least nobody had to edit your post to add code tags.

    Caution: Contents may have been coded under pressure.
      I just assumed that grep would behave the same way as split does.
      I was wrong.
      perl -e'print split /param=(.*)/, "param=value"'
      returns 'value', right?
      Thanks
        It does, but that's not the normal usage of split, either. You're saying that you've got a series of records separated by param=anything and that, in addition to returning the things that are separated by that, you also want to return the part in the parentheses.

        You can use the =~ operator to apply a regex to a string (which was what I showed you in my example). That is the straightforward way to do what you want. If you have a list or array of strings to apply, you can use map or foreach to set $_ to each of them in turn, and then you don't need the =~ operator, because a regex applies to $_ by default.


        Caution: Contents may have been coded under pressure.
Re: grep question
by japhy (Canon) on May 26, 2005 at 23:25 UTC
    Most people have been showing map { /param=(.*)/ ? $1 : () }, but if you're using list context (like print() supplies), you can just write map { /param=(.*)/ }.

    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: grep question
by tlm (Prior) on May 26, 2005 at 21:45 UTC

    Why grep? The purpose of grep is to filter a list according to some criterion, which doesn't sound at all like what you want to do. Of course, if one is hellbent on using grep for this, Perl will oblige with WTDIs galore, but this hardly qualifies as an argument in favor of using grep here.

    the lowliest monk

      Of course, if one is hellbent on using grep for this, Perl will oblige with WTDIs galore...

      One such solution:

      perl -e 'print grep { s/param=// } @{[ "param=value" ]};'

      ...but this hardly qualifies as an argument in favor of using grep here

      Agreed. Other than as a proof-of-concept, don't do this. I'd personally use map for the OPs exact stated desire. I suspect, though, if the OP gave the larger context of the problem, better solutions might be apparent.

        Personally, I'd use both map and grep for what the OP is doing:

        return map { /memtype=(.*)/i; $1 } grep /memtype=/, $self -> collect_d +ata ('all');
        I realise that this probably doesn't speed things up, maybe even slows it down. But it does what it says much more obviously to me. I'm collecting all the data. Then I'm extracting just the ones I want (memtype), and then I'm grabbing the stuff on the right of the equals sign. Just seems more straightforward to me. As for brian d foy's concern about using $1 when you haven't checked if it matched, I hope this is ok - I agree with him, and I think this is ok. ;-)

Re: grep question
by trammell (Priest) on May 26, 2005 at 21:26 UTC
    One possible solution:
    perl -le 'print map {/param=(.*)/;$1} "param=value";'
    I just hope you're not planning on using this to process CGI arguments...

      I think you meant:

      perl -le 'print map { /param=(.*)/ ? $1 : () } "param=value";'

      $1 is only set if the match is succesful.

      (merlyn i beat you to it ;-)

      ---
      $world=~s/war/peace/g

        No, the OP describes the input as a 'param=value' list. I stand by my post.
      Thanks

      Thanks for all the advises

      I actually had tried something like  map { /param=(.*)/; return $1; } which did not work.

      I have modified my code to be like this  return map { /memtype=(.*?)"/i ? $1 : (); } $self -> collect_data ('all'); as suggested by you monks!

      PS: I hope at least the reply post looks better !!