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

Short diescription: I want to use object created by qr// operator in "REPLACE" part of s/SEARCH/REPLACE/ operator... Reason is quite simple - I have to path Pattern as parameter into subroutine... Code example:
$old_db="emdb1"; $new_db="kuku"; $string="AUTHORIZATION,libctl62-m.sl,CONTROLM,emdb1,b02ed6600206ca161d +165355c67b72073b6123d6838f1f68203b78cb9c4c63c9,emdb2,,;" ; $str_regexp = "\$1\$2\$3${new_db}," ; $string=~s/([^,]*,)([^,]*,)([^,]*,)([^,]*,)/$str_regexp/e; print "${string}\n";
I supposed result to be:
"AUTHORIZATION,libctl62-m.sl,CONTROLM,kuku,b02ed6600206ca161d165355c67b72073b6123d6838f1f68203b78cb9c4c63c9,emdb2,,;" ;"
But actually - it is:
"(?x-ism:"\$1\$2\$3kuku,")b02ed6600206ca161d165355c67b72073b6123d6838f1f68203b78cb9c4c63c9,emdb2,,;"
What is my mistake? Can it be done in mome way?

Edit: g0n - code tags round long output lines

Replies are listed 'Best First'.
Re: use qr// variable in right side of s/// operator
by mk. (Friar) on Feb 15, 2006 at 12:10 UTC
    maybe try using eval()?!
    $old_db="emdb1"; $new_db="kuku"; $string="AUTHORIZATION,libctl62-m.sl,CONTROLM,emdb1,b02ed6600206ca161d +165355c67b72073b6123d6838f1f68203b78cb9c4c63c9,emdb2,,;" ; $str_regexp = "\$1\$2\$3${new_db}," ; $string=~eval(s/([^,]*,)([^,]*,)([^,]*,)([^,]*,)/$str_regexp/e); print "${string}\n";


    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    @
      Hi mk! I tried... $string remains unchanged... It is also interesting question - that I have no ansver - why... But any way - it does not solve a problem...
        oh, i'm sorry, i guess i'd misunderstood your problem.
        $old_db="emdb1"; $new_db="kuku"; $string="AUTHORIZATION,libctl62-m.sl,CONTROLM,emdb1,b02ed6600206ca161d +165355c67b72073b6123d6838f1f68203b78cb9c4c63c9,emdb2,,;" ; $string =~ s/$old_db/$new_db/g; print $string;
        does it work properly now?!
        =)


        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        @
Re: use qr// variable in right side of s/// operator
by brian_d_foy (Abbot) on Feb 15, 2006 at 14:42 UTC

    You need a double evaluation there. The first /e puts the contents of $str_regex into the replacement, and the second /e evaluates the contents as Perl code. Notice I double quote around $str_regex: one to quote it, and one for the Perl code I'll evaluate later.

    $old_db = "emdb1"; $new_db = "kuku"; $string = "AUTHORIZATION,libctl62-m.sl,CONTROLM,emdb1,b02ed6600206 +ca161d165355c67b72073b6123d6838f1f68203b78cb9c4c63c9,emdb2,,;" ; $str_regexp = '"$1$2$3$new_db,"' ; $string =~ s/([^,]*,)([^,]*,)([^,]*,)([^,]*,)/$str_regexp/ee; print "$string\n";

    Also, the right hand side is just a double quoted string. It's not a regexp in any way.

    Lastly, if you're manipulating anything more complex regularly, you might want to use one of the comma separated value modules on CPAN rather than doing it yourself.

    Good luck :)

    --
    brian d foy <brian@stonehenge.com>
    Subscribe to The Perl Review
      Keep in mind that since the second 'e' causes the content of $str_regexp to be executed as Perl code, it would be dangerous to accept $str_regexp from a remote source such as a web page form. For example, consider what would happen if someone passed "system('rm -rf /')".

        Well, all the /e's evaluate the replacement string as Perl code. :)

        --
        brian d foy <brian@stonehenge.com>
        Subscribe to The Perl Review
Re: use qr// variable in right side of s/// operator
by Tanktalus (Canon) on Feb 16, 2006 at 01:06 UTC

    This seems to come up from time to time. My suggestion remains this piece of code which avoids the eval security concerns that ikegami brings up by avoiding the extra level of eval. If you took that sub, you would call it like this:

    $string = substitute($string, '([^,]*,)([^,]*,)([^,]*,)([^,]*,)', $s +tr_regexp);
    However, since this is a comma-separated-value (CSV) file, where you are actually exchanging a given value in the line, I'd definitely second the suggestion to use Text::CSV or Text::xSV or Text::xSV_XS or even DBD::CSV. Then there's no regular expression - you just set $row[3] = $new_db and you're done.