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

my $data = '#define MANUFACTURER "xyz"'; my $replace = '#define MANUFACTURER(\s+)"xyz"'; my $replace_with = '#define MANUFACTURER$1"abcd"'; $data =~ s/$replace/$replace_with/g;; print $data;

Expected Output is : #define MANUFACTURER "abcd" (with appropriate number of spaces)

But the output that i am geting is: #define MANUFACTURER$1"abcd"

In the actual usage scenario, variables $data, $replace and $replace_with are read from a file. How to get the expected output?

Replies are listed 'Best First'.
Re: Problem with Pattern matching and substitution using variables
by kennethk (Abbot) on Sep 09, 2011 at 17:04 UTC
    Your issue is that once you have the literal $ character in your replacement string, you must run the string through an eval in order to get Perl to interpret the variable. You could accomplish this with the code

    my $data = '#define MANUFACTURER "xyz"'; my $replace = '#define MANUFACTURER(\s+)"xyz"'; my $replace_with = '"#define MANUFACTURER$1\"abcd\""'; $data =~ s/$replace/$replace_with/eeg; print $data;

    See Search and replace in perlretut for a bit more detail. Note this should not be done if the data in $replace_with is at all untrustworthy.

      Why is the second /e switch needed to properly eval the replace pattern? In trying it out, I see it clearly is, but I'm missing something here in trying to reason it out. I'm confused as to why a single /e and no switch produce the same result.

        As documented in s/PATTERN/REPLACEMENT/msixpodualgcer in perlop:
        Otherwise, if the PATTERN contains a $ that looks like a variable rather than an end-of-string test, the variable will be interpolated into the pattern at run-time.
        ...
        e Evaluate the right side as an expression.
        ee Evaluate the right side as a string then eval the result.
        Essentially, with no switch, the variable is interpolated following qq rules. With one e, the value between the slashes is evaluated; all that lies between the slashes is the scalar, so it evaluates equivalently. With two es, the scalar is evaluated into the string value, and then that string value is passed through eval.