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

Hello,

I am trying to match and replace something, but I can't get it to work. Could you please help?
Example string:
$query = 'foo=bar&blah=ha'
I want to replace the value of bar with TEST. bar could either be followed by another ampersand or $ (end of line). I want a non-greedy match.
I am trying something like this, but it is not working.(It is always matching till end of line and it is swapping foo as well:(
$query =~ s/foo=(.+?)?\&|$/TEST/g;
Thank you very much!

Replies are listed 'Best First'.
Re: REGEX question
by johngg (Canon) on Jun 09, 2008 at 23:46 UTC
    This seems to work on your string but no further testing done so caveat emptor :-) You were replacing 'foo' because you matched it explicitly in the LHS of the substitution.

    $ perl -le ' > $str = q{foo=bar&blah=ha}; > $str =~ s{(?<=foo=)[^&]+(?=&|\z)}{TEST}g; > print $str;' foo=TEST&blah=ha $

    Cheers,

    JohnGG

Re: REGEX question
by GrandFather (Saint) on Jun 10, 2008 at 01:13 UTC

    johngg has given a solution, but it may leave you wondering what is going on somewhat. The magic is a look behind assertion (the (?<=...) bit). It matches the given match condition (which must be a fixed length). It makes sure that the stuff matches, but the matched stuff is not part of the string that will be replaced. See perlretut and perlre for regex documentation.


    Perl is environmentally friendly - it saves trees
Re: REGEX question
by Jenda (Abbot) on Jun 10, 2008 at 02:10 UTC

    Are you sure the thing you want to replace the "bar" with will always be properly escaped? Keep in mind that if it would contain a & or a space or one of the several other problematic characters then the result would be invalid?

    It would probably be better to use some module to parse the querystring, change the data and build a querystring again. CGI or CGI::Deurl+CGI::Enurl or ...