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

I have a simple script that searches for patterns in text, and then removes matches (the main line of code not much more than $line =~ s/$var//;).

I have discovered that if $var contains a set of parentheses, this does not work as expected (the text does not get removed).

I don't really understand the theory behind this (or what exactly happens), but I assume that I need to somehow pass the variable in a way to tell perl that I want to use the literal variable.

How do I do that? And what exactly does perl try to do with:

$var = 'apple (banana) cherry'; $line = 'apple (banana) cherry kiwi lemon melon'; $line =~ s/$var//;

Replies are listed 'Best First'.
Re: newbie quoting question
by blakem (Monsignor) on Sep 23, 2001 at 04:01 UTC
    The parens are being interpreted as special chars inside the regex. Use the quotemeta operator to escape them, and they'll retain their literal meaning.
    $line =~ s/\Q$var//;
    As in:
    #!/usr/bin/perl -wT use strict; my $var = 'apple (banana) cherry'; my $line = 'apple (banana) cherry kiwi lemon melon'; $line =~ s/\Q$var//; print "$line\n"; =output kiwi lemon melon

    -Blake

Re: newbie quoting question
by John M. Dlugosz (Monsignor) on Sep 23, 2001 at 07:04 UTC
    To add to what blakem said, \Q is the "begin" and \E is the "end". He left off the \E because the $var was the last thing in your pattern. But in the general case, you'll use both. e.g. m/prefix\Q$var\Esuffix/. Do that anytime you have a $var in a pattern that you want taken literally, as opposed to containing more regex instructions.

    $s="a*"; /$s/; # same as /a*/, finds a string of a's /\Q$s\E/; # same as /a\*/, literally matches "a*" characters.
Re: newbie quoting question
by George_Sherston (Vicar) on Sep 23, 2001 at 16:27 UTC
    what exactly does perl try to do with:

    To find a full answer to that you need to look up capturing and clustering. But in short, as I understand it, if you give the regex engine your $var, it does this:

    (1) looks for apple banana cherry;
    (2) if it finds it, "captures" banana into a "dynamically scoped variable", which in this case will be $1 because it's the first capturing you've done.

    The function of the brackets is to tell the regex engine which bit of the stuff you're searching for you want to capture. So it doesn't search for brackets. Which is why in your case it doesn't match.

    You would have got a match with
    $line = 'apple banana cherry kiwi lemon melon';
    and you would have found that after you did
    $line =~ s/$var//;
    $1 miraculously returned "banana".

    (Of course that wouldn't be very interesting, because you already knew it was a banana, which is why brackets usually have something other than literal characters in them).

    § George Sherston
Re: newbie quoting question
by NearO (Scribe) on Sep 24, 2001 at 12:46 UTC
    As George_Sherston mentioned above, the parentheses put a banana into $1. Here is just another way to circumvent that:
    $var = quotemeta('apple (banana) cherry'); $line = 'apple (banana) cherry kiwi lemon melon'; $line =~ s/$var//;
    That would be equal to:
    $var = 'apple \\(banana\\) cherry'; $line = 'apple (banana) cherry kiwi lemon melon'; $line =~ s/$var//;
    Thus perl wouldn't catch the banana, because the parentheses were escaped.
    -- 
    arneb@emergency:~ > perl -MO=Deparse -e "(0); #Confusing perl..." 2> /dev/null
    '???';
    arneb@emergency:~ >