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

Hi,

The demo:
#!perl -l use strict; use warnings; my $orig = 'a.dll'; my $replacement = 'b.dll'; my $str1 = "foo $orig bar"; my $str2 = $str1; $str1 =~ s/\Q$orig\E/\Q$replacement\E/g; $str2 =~ s/\Q$orig/$replacement/g; print $str1; print $str2;
I expected $str1 and $str2 to be identical after the substitution regexes, but they're not (on both perl-5.16.0 and 5.20.0 at least). For me, the demo outputs:
foo b\.dll bar foo b.dll bar
Why does the first regex put that backslash in there ?
Are we allowed a maximium of *one* \Q per regex ?
Is there documentation that explains this ?

Supposing that instead of the first regex, I had wanted to do:
$str1 =~ s/\Q$orig\E.+/\Q$replacement\E/g;
$str1 would then have become foo b\.dll, whereas I expected foo b.dll.

Cheers,
Rob

Replies are listed 'Best First'.
Re: A misunderstanding of quotemeta ?
by LanX (Saint) on Jun 04, 2014 at 02:44 UTC
    quotemeta
    Returns the value of EXPR with all non-"word" character +s backslashed. (That is, all characters not matching "/[A-Za-z_0-9]/" will be preceded by a backslash in the returned string, regardless of any locale settings.) T +his is the internal function implementing the "\Q" escape in d +ouble- quoted strings.

    So the dot is backslashed.

    Other question, why do you quotemeta the RHS of a s/// ?

    Which problem are you trying to solve?

    Cheers Rolf

    (addicted to the Perl Programming Language)

      Other question, why do you quotemeta the RHS of a s/// ?

      Duh - there's no need to quotemeta the RHS.

      Which problem are you trying to solve?

      The problem of my own idiocy. (It's an ongoing exercise.)
      Thanks, guys.

      Cheers,
      Rob
Re: A misunderstanding of quotemeta ?
by Athanasius (Archbishop) on Jun 04, 2014 at 02:52 UTC

    Hello syphilis,

    From quotemeta:

    quotemeta (and \Q ... \E) are useful when interpolating strings into regular expressions, because by default an interpolated variable will be considered a mini-regular expression.

    So, the purpose of using \Q is to prevent “special” characters from having their special (overloaded) meanings within regular expressions. And this is done by backslashing the characters:

    ... all ASCII characters not matching /[A-Za-z_0-9]/ will be preceded by a backslash in the returned string, ...

    Now, in a substitution, only the left-hand side is a regex; the right-hand side is simply the replacement text. So it makes no sense to “de-regexify” the special characters on the right-hand side; they have no special regex meaning in this position anyway. But if you do apply \Q, of course the non-word characters are backslashed, as you are seeing.

    That’s my understanding, anyway. Hope it helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: A misunderstanding of quotemeta ?
by AnomalousMonk (Archbishop) on Jun 04, 2014 at 04:13 UTC

    It may be helpful to consider  \Q...\E quotemeta interpolation in a string-only context, entirely divorced from regexification. These escapes control meta-quoting in any double-quote evaluation, of which a regex is only one instance.

    c:\@Work\Perl\monks>perl -wMstrict -le "my $interp = 'a.b'; my $string = qq{--\Q$interp\E--}; print qq{'$string'}; ;; my $strung = qq{--$interp--}; print qq{'$strung'}; " '--a\.b--' '--a.b--'