in reply to variable interpolation in regexps

You're running into regular expression meta characters, like $. You want to look at perlre and use \Q...\E or quotemeta for interpreting your string as literal characters in regular expression interpolation:

my $regexp = qr/\Qsome$thing\E/; ... if (/$regexp/) {

or alternatively

my $regexp = quotemeta('some$thing'); ... if (/$regexp/) {

Replies are listed 'Best First'.
Re^2: variable interpolation in regexps
by cdarke (Prior) on Nov 24, 2006 at 14:38 UTC
    With respect I don't think it is seeing $ as an RE meta-character, but interpolation is looking for a variable called $thing. My understanding is that $ only means 'end-of-text' at the end of an RE expression, unless /m is specified.
    Using \Q will still fix it though.

      I now realize that I only saw half of the problem. The wanted idea seems to be double-interpolation of 'some$thing' into "someTHING" by replacing the string '$thing' within $regexp with the value of the variable $thing.

      Your points are close but wrong - Perl allows stuff to appear in regular expressions after the $ metacharacter. Otherwise, Perl regular expressions act like double-quoted strings and hence interpolate only once:

      #!perl -wl use strict; my $regexp = 'some$thing'; my $thing = 'THING'; my $target = 'this is some$thing strange.'; print $regexp; print $target; print '$target =~ /$regexp/ ', $target =~ /$regexp/; print '$target =~ /\Q$regexp\E/ ', $target =~ /\Q$regexp\E/; print '$target =~ /some\$thing/ ', $target =~ /some\$thing/; print '$target =~ /some$/ ', $target =~ /some$/; my $eol_in_the_middle = qr/some$(?:thing)/; print 'eol_in_the_middle ',$eol_in_the_middle; print '$target =~ /$eol_in_the_middle/ ',$target =~ /$eol_in_the_middl +e/;

      Of course, it's kinda hard to make $eol_in_the_middle match, but you can do it by using the /m switch and changing the RE and target string a bit:

      my $eol_in_the_middle2 = qr/some$(?:\s*thing)/; my $target2 = "this is some\nthing strange."; print '$target2 =~ /$eol_in_the_middle2/ ',$target2 =~ /$eol_in_the_mi +ddle2/sm;
Re^2: variable interpolation in regexps
by Locutus (Beadle) on Nov 24, 2006 at 14:44 UTC
    Thanks, Corion, for
    - responding so quickly,
    - pointing me to the relevant documentation, and
    - providing the two code snippets which do the one (double interpolation by means of qr{\Q...\E}) or the other trick (single interpolation by means of quotemeta).

    I'm a little astonished that obviously none of these two is the default behaviour of Perl. May I ask you (or any of the other Monks reading) to explain why exactly /$regexp/ is always false in my examples? I would really like to understand what's going on "inside" if I use neither qr{\Q...\E} nor quotemeta, i.e. for which value of $_ the condition would be true.

      I first didn't understand what you want to do, but cdarke pointed me to it.

      It seems you want to solve two problems:

      Firstly, you want to use the value in $regexp as some kind of template which later on uses the value of $thing to replace the string $thing within some$thing. This does not happen, because regular expressions are, to Perl, more or less like double-quoted strings (see perlop, section Quotes and quote-like operators). So, your $regexp will always remain some$thing and never access the value of the variable named $thing.

      \Q...\E don't do double interpolation, they do quoting, so the regex meta characters are not seen as meta characters anymore and thus don't help you with your problem.

      Having double interpolation the default in Perl would be horrendous, because after double interpolation immediately follows triple interpolation whenever you're using a double-interpolated string in any string context, which would make it nearly impossible to use any modules that construct strings or regular expressions.

      To solve your problem at hand, doing template-like replacement on a string, you don't want to use a variable (and its name), but a hash which contains the name/value pairs:

      my $regexp = 'some$thing'; my %values = ( 'thing' => 'THING', # ... other value mappings ); print $regexp; $regexp =~ s/\$(\w+)/$values{$1}/ge; print $regexp;

      If you're still wondering, yes, it's possible to do the replacement on variables by name too, but Dominus has explained far much better why it's stupid to use a variable as a variable name.

      To address your last question, the regular expression formed by $regexp = qr/some\$thing/ matches any string that contains the substring some$thing literally, that is, with a dollar sign in the middle.