http://qs321.pair.com?node_id=525803


in reply to Unrecognized escape \Q passed through in regex

\Q and \E don't work inside interpolations. They only work in regexp literals (m/here/, s/here// and qr/here/). Solutions:

# Text. $text = 'Renata'; $window =~ /\b\Q$text\E\b/ism
and
# Uncompiled regexp. $text = 'Renata'; $regexp = '\\b' . quotemeta($text) . '\\b'; $window =~ /$regexp/ism
and
# Compiled regexp. $regexp = qr/\b\QRenata\E\b/ism; $window =~ $regexp

Note:
The s modifier is useless if you don't use ".".
The m modifier is useless if you don't use "^" or "$".

Replies are listed 'Best First'.
Re^2: Unrecognized escape \Q passed through in regex
by Articuno (Beadle) on Jan 26, 2006 at 18:39 UTC
    Ok,I'll go with something along the lines of the second solution...

    I know the meaning of the switches... They are there because some regexen on DB are allowed to be "real regexes" and not just "bare words".

    Maybe I'll emulate \Q...\E then...
    $regexp =~ s/\\Q(.*?)\\E/quotemeta($1)/eg;
    Should that do what I want ? :-)
    update: /e ==> /eg
    -- 6x9=42

      Not necessarily. It won't work for

      print($regexp) Expect Gives -------------- ------------ ---------- \Q*\E\Q*\E \*\* \*\Q*\E \Q**LOL** \*\*LOL\*\* \Q**LOL** \\Quit\\Exit \\Quit\\Exit \Quit\Exit \Qfoo\\E foo\\\\E foo\\

      Solution:

      my $in_quote = 0; $regexp =~ s/([^\\]|\\.)/ if ($in_quote) { if ($1 eq '\\E') { $in_quote = 0; '' } else { quotemeta($1) } } else { if ($1 eq '\\Q') { $in_quote = 1; '' } else { $1 } } /eg;

      Update: Alternative:

      $regexp =~ s/ \G ( (?:[^\\]|\\[^Q])* ) (?: \\Q (?:[^\\]|\\[^E])* (?:\\E)? )? / $1 . (defined($2) ? quotemeta($2) : '') /xge;

      Neither snippet is fully tested. In fact, both are known to be unable to handle regexps in which (?{...}) or (?{{...}}) are used. What's wrong with what I suggested in my earlier post?

        But what's wrong with what I suggested in my earlier post?

        The regexes are in a DB. In the beginning, all of them where full regexes (no need for \Q...\E, etc...). But now, some of them are created by an user with a GUI. These "new" regexes are "plain text", and I want to ignore the metacharacters of *them* only, and not of all the regexes. If I "quotemeta" any regex i see, I can end up quoting real regexes :-(

        Oh, and the interface is not in Perl, so I don't have quotemeta there. All I can do is surround with \Q...\E and hope it works, but as I found out (the bad way), it doesn't :-(
        -- 6x9=42
Re^2: Unrecognized escape \Q passed through in regex
by merlyn (Sage) on Jan 27, 2006 at 03:45 UTC
    \Q and \E don't work inside interpolations. They only work in regexp literals
    Fascinating theory, but easily proven wrong:
    print "\Qabc*def\E\n"; # prints abc\*def
    The truth is that \Q means "add backslashes to special chars until \E" in the exact same places that \n becomes a newline and $x expands to its value: every double-quoted string. A regex (that doesn't have special single-quote quoting) is just one example of that.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      \Q and \E don't work inside interpolations. They only work in regexp literals
      Fascinating theory, but easily proven wrong:
      print "\Qabc*def­\E\n"; # prints abc\*def

      Your example shows a \Q being used inside of a quoted string, not inside of a string value being interpolated (into a string or regex). You've misunderstood how "interpolation" was originally used.

      I'll agree that the original use of "interpolation" wasn't clear enough. Though, double-quoted strings allow interpolation but I wouldn't call a quoted string that didn't contain any variables "an intepolation".

      - tye        

      I thought it worked in double-quoted literals, but my test showed otherwise. I must have made a typo in my test. In any case, that \Q works in double-quoted litarals doesn't help the OP any.