Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   \Q acts differently in s/// and m// operations (http://www.velocityreviews.com/forums/t890885-q-acts-differently-in-s-and-m-operations.html)

gargoyle 02-17-2005 01:42 AM

\Q acts differently in s/// and m// operations
 
Consider the following code:

#!/usr/bin/perl -w
# NOTE: don't focus on the backslashes, I already know Win32 can
# use / instead. This is simply a regex+metachar question...

$old = 'C:\\test\\1\\'; # old parent dir
$new = 'C:\\test\\2\\'; # new parent dir
$path = 'C:\\test\\1\\bin\\'; # the path we're renaming
warn "old=$old, new=$new, path=$path\n";

warn "----- doing match! -----\n";
$path =~ /^(\Q$old\E)/; # this matches
warn "captured \$1 = $1\n";
$path =~ /^(\Q$new\E)/; # this doesn't
warn "captured \$1 = $1\n";
warn "old=$old, new=$new, path=$path\n";

warn "----- doing substitution! -----\n";
$path =~ s/^\Q$old\E/\Q$new\E/;
warn "old=$old, new=$new, path=$path\n";
__END__

The output:

old=C:\test\1\, new=C:\test\2\, path=C:\test\1\bin\
----- doing match! -----
captured $1 = C:\test\1\
captured $1 = C:\test\1\
old=C:\test\1\, new=C:\test\2\, path=C:\test\1\bin\
----- doing substitution! -----
old=C:\test\1\, new=C:\test\2\, path=C\:\\test\\2\\bin\

In the m// operation, the captured output is the original variable, not
the quotemeta version.

But in the s/// operation, the output is quoted.

Why are they behaving differently? And is there a way to get unquoted
output from the s/// operation, or am I just better off using substr(),
since after all there's no unquotemeta() function?


Bob Walton 02-17-2005 02:36 AM

Re: \Q acts differently in s/// and m// operations
 
gargoyle wrote:

....
> In the m// operation, the captured output is the original variable, not
> the quotemeta version.
>
> But in the s/// operation, the output is quoted.
>
> Why are they behaving differently? And is there a way to get unquoted
> output from the s/// operation, or am I just better off using substr(),
> since after all there's no unquotemeta() function?
>


Well, the "replacement" in the s/// operator is a *string*, not a
regexp. And that string is processed per qq(). For that, \Q has
a different meaning -- all non-word characters following \Q are
quoted, just as you noted above. In the m// regexp, it is the
*regexp* characters that are quoted, and not any characters in
the matched string. You probably should simply dispense with the
\Q and \E in your replacement string. For details, see:

perldoc perlop

particularly the sections on quote and quote-like operators and
on regexp quote-like operators.

And there *is* an "unquotemeta" function for a string quoted by
\Q -- eval(qq(qq/$string/)) should do the trick, I think, as in:

d:\junk>perl -e "$a=qq(ab\Q~!@#\E~!@#);print eval qq/qq($a)/"
ab~!@#~!@#
d:\junk>

--
Bob Walton
Email: http://bwalton.com/cgi-bin/emailbob.pl

gargoyle 02-17-2005 03:19 AM

Re: \Q acts differently in s/// and m// operations
 
On 2005-02-17, Bob Walton <see.sig@rochester.rr.com> wrote:
> Well, the "replacement" in the s/// operator is a *string*, not a
> regexp. And that string is processed per qq(). For that, \Q has
> a different meaning -- all non-word characters following \Q are
> quoted, just as you noted above.


Aha! Now I understand. Thanks for clearing that up.

> And there *is* an "unquotemeta" function for a string quoted by
> \Q -- eval(qq(qq/$string/)) should do the trick, I think, as in:
>
> d:\junk>perl -e "$a=qq(ab\Q~!@#\E~!@#);print eval qq/qq($a)/"
> ab~!@#~!@#
> d:\junk>


Interesting... But I have trouble understanding the impact of several
levels of quoting and interpolation. It's late though, so I'll re-read
the perlop manpage tomorrow and see if I can make sense of it.

Ilya Zakharevich 02-17-2005 10:57 PM

Re: \Q acts differently in s/// and m// operations
 
[A complimentary Cc of this posting was sent to
Bob Walton
<see.sig@rochester.rr.com>], who wrote in article <crTQd.15377$H05.4135@twister.nyroc.rr.com>:
> Well, the "replacement" in the s/// operator is a *string*, not a
> regexp. And that string is processed per qq().


Correct.

> For that, \Q has
> a different meaning


Wrong. \Q has the same meaning everywhere.

> -- all non-word characters following \Q are quoted


That's it.

> In the m// regexp, it is the *regexp* characters that are quoted,
> and not any characters in the matched string.


Wrong. But since quoting some characters is a NOOP (e.g., \: matches
the same as : ), the semantic is somewhat similar to what you wrote -
which is probably the reason for your confusion.

> You probably should simply dispense with the \Q and \E in your
> replacement string.


Without reading the mind of the author, giving any advice does not
make sense. I would just note that

s(REX)(\Q$var);

is the same as

$repl = quotemeta $var;
s(REX)($repl);

(but the first version is much harder to debug).

Hope this helps,
Ilya


All times are GMT. The time now is 04:59 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.