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

Myself and a colleague cannot get $1 in the code snippet below to work and are wondering what we're doing wrong with respect to our understanding/usage of eval:

(This is using perl v 5.8.8. )
$strvar = "test text"; $pattern = "\$strvar =~ s/(text)/\\[tag]$1\[/tag]/ig"; eval $pattern;
example output:
test [tag]text[/tag]

current output:
test [tag][/tag]

Thanks in advance for your assistance.

Replies are listed 'Best First'.
Re: Eval Function Question
by Fletch (Bishop) on Nov 04, 2009 at 20:07 UTC

    a) you didn't backwhack the second dollar sign ($1) so you it's not getting passed through to be seen by eval; 2) this is possibly a simplified example, but you really don't need to use eval to do this; III) the /e modifier (or some number of them) may do what you think you need to use an eval of the entire statement for.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Thank you both for your answers. The second backwhack takes care of the problem. I'm sure we tried that in one of our iterations of the script. Oh well, it works now.
      -Brian

        By the way, you probably should not be doing it at all. eval has teeth: $strvar = "test text \@{[ `rm -rf /' ]) # sic"; for contrived example. There is almost guaranteed to be a better/safer way to do whatever you want. Check what Fletch said about the e flag to start with. If that doesn't cover your needs, probably should ask about the problem you're trying to solve and not just the code that won't work.

Re: Eval Function Question
by keszler (Priest) on Nov 04, 2009 at 20:06 UTC
    The $ in $1 is not backslash-escaped. Typo here, or missing in your code?
Re: Eval Function Question
by ikegami (Patriarch) on Nov 04, 2009 at 20:53 UTC
    Why not simply use
    $strvar =~ s/(text)/[tag]$1[\/tag]/ig;
      I asked my colleague to assist me to describe why we ended up down this path:
      1. We need to read regular expression statements from a file. 2. The statements get read in from a file into a string and then need to be evaluated.
      3. He put the whole replacement regex into a string, but neither of us recall now the reason for needing to do so.
      4. We ultimately realized after reviewing the post that we needed to escape the [ that followed our $1 replacement -- we're guessing that $1[ looked like the opening part of an array.
      5. Anyway, the answers posted here were indeed correct and assist us greatly to get our escape characters in the proper locations in the source regex file we're using.

      -Brian

        Still. Don't do it. :)

        perl -MYAML -e 'print Dump({my_rx => qr/match this/ })' --- my_rx: !!perl/regexp (?-xism:match this)

        1. We need to read regular expression statements from a file. 2. The statements get read in from a file into a string and then need to be evaluated.

        No need for eval for that. s/$pattern_from_file/.../ works fine on its own.


        I could see you using eval is you had the following code pattern and you wanted $r to interpolate captures in $s (e.g. $1):

        my $s = '...'; my $r = '...'; s/$s/$r/

        In other words, if you wanted $r to be a template. The problem is that eval makes a very poor template system.