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

... at least I think it will be.

I need to search a string for characters that will be interpreted as metacharacters, like + $ ^ etc, and put the backslash in front so they don't get interpreted that way. Here's how I could do it by substituting just one metacharacter at a time:

$_ =~ s/\+/\\+/; $_ =~ s/\$/\\$/; $_ =~ s/\^/\\^/;
How can I do it in one line? I'm looking for a metacharacter to put into the second half of the substitution regex that basically says, "Take whatever character you matched from the first part and put it back in here". It might look like:
$_ =~ s/(\+|\$|\^)/\\*/;
but with something in place of the *

Thanks in advance - hope the answer's not too obvious & I'm really overlooking something.

Replies are listed 'Best First'.
Re: Simple search question ...
by throop (Chaplain) on Jun 13, 2008 at 23:20 UTC
    Gentle mwhiting

    It would help to know more about what you are going to do with this string when you have it. You can leave the + $ ^ characters in place and protect them with \Q:

    my $foo = 'a\b*c/d'; my $bar = ' A\B*C/D '; $bar =~ / ^ \s+ \Q $foo \E \s+ $/xi
    will evaluate true.

    But if you really want to, know that it is 'safe' to backslash all the punctuation characters, so

    s/([^\w\s])/\\$1/g
    should do what you want. More specifically, backslashing alphanumeric characters makes them 'meta', but only alphanumeric characters become 'meta' when backslashed. So even though you don't need to backslash '#', it will match the same even after it's backslashed.

    throop

Re: Simple search question ...
by swampyankee (Parson) on Jun 14, 2008 at 00:47 UTC

    Either \Q or quotemeta. Either will let you avoid worrying about the possibility of missing an odd case.


    Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

Re: Simple search question ...
by casiano (Pilgrim) on Jun 14, 2008 at 07:39 UTC
    As swampyankee points out two solutions are to use \Q or quotemeta. If you want to quote only a subset of metacharacters then the fact that most metacharacters loss their status inside classes can help:
    $ perl -wde 0 main::(-e:1): 0 DB<1> $_ = 'a+b*^c$]d' DB<2> s/([+*^\$\]])/\\$1/g DB<3> p $_ a\+b\*\^c\$\]d

      Thanks to all of you. The $1 was really what I was looking for. The /q is helpful too, I'll use that. Thanks muchly!