R. Joseph Newton wrote:
> Rob Dixon wrote:
>
> > Hi Scott, Francesco.
> >
> > Scott R. Godin wrote:
> > > Francesco Del Vecchio wrote:
> > >
> > > > suppose this:
> > > > ======================================
> > > > $string 'I saw Roger and I said :roger? what the @*$!';
> > > >
> > > > $var1 = "roger? what the @*$!";
> > > > $var2 = "Hi roger...nice to meet you";
> > > >
> > > > $string=~ s/$var1/$var2/;
> > > > =======================================
> > > >
> > > > I'm having problems....due (i suppose) to the special chars in
> > > > the $var1 string the s/// don't match anything.
> > > > What can I do to?
> > >
> > > s{\Q$var1\E}{$var2} is usually what you want, except that may very
> > > well 'quote' out the $ in $var.
> >
> > I guess you mean $var2? The replacement expression will
> > only be interpolated once. Any variable names embedded in the
> > contents of $var2 will be copied verbatim.
> >
> > > I suspect what you really want is
> > >
> > > $var1 = qr{roger? what the @*$!};
> >
> > This won't work, I'm afraid. The $! will be interpolated
> > unless the delimiters are single-quotes:
> >
> >     print (my $var1 = qr{roger? what the @*$!});
> >
> > output
> >
> >     (?-xism:roger? what the @*)
> >
> > > ( perldoc -f qr ) (perldoc perlre) and (perldoc perlop) for more
> > > details.
> >
> > Maybe what is wanted is:
> >
> >     $var1 = quotemeta q{roger? what the @*$!};
> >
> > which is the equivalent of the \Q...\E construct, but
> > applicable to an existing string.
> >
> > HTH,
> >
> > Rob
>
> Hi Rob,
>
> Well, almost there.  FWIW, the poison characters are the regex
> control characters [?*$]. The at symbol and exclamation mark worked
> fine.

Context, context, context! In the statement

    my $var1 = qr{roger? what the @*$!};

the string is in 'double-quote' context, ans so will attempt to expand
the scalar $! (the latest C library errno) which in my example was
unset, so the two characters disappeared. The array would be
similarly interpolated if it was a built-in or named with 'word'
characters.

Once this is done, the string goes through compilation as a regex,
which applies magic to the metacharacters:

    qw< \ ^ . $ | ( ) [ ] * + ? { } >.

At this point the question mark and star act as quantifiers on the
'r' and @ respectively, and require escaping to avoid this.

> I also encountered the (?-xism:roger\? what the [EMAIL PROTECTED]) using
> qr.

How do you get this with a plain qr()? I can only achieve it
by manually escaping these characters: \Q also escapes the
spaces for you.

> My first try with quotemeta q() also had some issues:
>
> #!/usr/bin/perl -w
>
> use strict;
>
> my $string;
> $string = 'I saw Roger and I said :roger? what the @*$!';

OK, single-quote context, so no escaping and no interpolation.
Actually, the sequences \\ and \' are changed to \ and ' (the
latter being whatever delimiter is used for the string
representation) but no other changes are made. The string is
stored 'as-is'.

> my $var1 = quotemeta q(roger? what the @*$!);

    $var1 eq 'roger\?\ what\ the\ [EMAIL PROTECTED]'

> my $var2 = quotemeta q(Hi roger...nice to meet you);

    $var2 eq 'Hi\ roger\.\.\.nice\ to\ meet\ you'

>
> $string =~ s/$var1/$var2/e;

FIrstly the pattern string undergoes double-quote
interpolation and because of the /e, the replacement
expression $var2 gets executed instead of interpolated.
In the case of a simple string value this amounts to the
same thing.

So the match string is

    roger\?\ what\ the\ [EMAIL PROTECTED]

which correctly has all regex metacharacters escaped,
while the replacement string is

    Hi\ roger\.\.\.nice\ to\ meet\ you

> print $var1 ."\n";
> print $string . "\n";
>
> E:\d_drive\perlStuff\guests>sub_roger.pl
> roger\?\ what\ the\ [EMAIL PROTECTED]
> I saw Roger and I said :Hi\ roger\.\.\.nice\ to\ meet\ you

So the pattern string is correct and the match succeeds, but the
replacement string has been modified by quotemeta as well,
and is reproduced as such.

> It does succeed in the substitution, though, the first trial using
> all the characters that did so.  So one more change, a backtrack:
> my $var2 = 'Hi roger...nice to meet you';
> and ...  Voila!:
> E:\d_drive\perlStuff\guests>sub_roger.pl
> roger\?\ what\ the\ [EMAIL PROTECTED]
> I saw Roger and I said :Hi roger...nice to meet you

Yes, exactly. You need to escape the metacharacters in the
pattern string but, since the regex metacharacters are
irrelevant to the replacement string you should simply make
sure that your variable contains exactly the characters you
want.

In my reply, I was using

    $var1 = quotemeta q{roger? what the @*$!};

as a replacement for Scott's

    $var1 = qr{roger? what the @*$!};

What both quotemeta and \Q do, by the way, is simply to
escape all \W (non-word) characters in the string. This
covers regex metacharacters, whitespace (when used in
conjunction with the /x modifier) and variable prefixes
($, @, %). Remember, though, that the \Q escaping is
done /after/ all other interpolation in the string, which is
why

    $var1 = quotemeta q{roger? what the @*$!};

is different from

    $var1 = qq{\Qroger? what the @*$!};

I hope this helps, and is clear: it's a bit of a minefield.
Alert readers please check for any mistakes! Thanks,

Rob




-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to