2

How does Perl do variable expansion in the m// match operator? What I have read is that m// only does variable expansion/interpolation once. But then why do I get Unmatched ( in regex when $pat is expanded ?

my $pat = '(\\)';
'\\' =~ /(\\)/  ? print "OK\n" : print "NO MATCH!\n";   # OK
'\\' =~ /$pat/  ? print "OK\n" : print "NO MATCH!\n";   # Unmatched ( in regex

my $pat2 = '(\\\)';
'\\' =~ /$pat2/  ? print "OK\n" : print "NO MATCH!\n";  # OK
4

Your problem is that you've misapplied or misremembered the arcane rules around backslashes.

In a single-quoted string literal,

A backslash represents a backslash unless followed by the delimiter or another backslash, in which case the delimiter or backslash is interpolated.

So the value of $pat is the three-character string (\), because the backslash in the source code is followed by another backslash and this stands for a single backslash. The value of $pat2 is the four-character string (\\), because the first two backslashes in the source code stand for one backslash, and the third backslash is followed by ) so it's left alone to be a second backslash in the string.

In a regular expression, a backslash quotes the next character unless it's alphanumeric. /$pat/ is equivalent to /(\)/, which is open-group followed by a literal close parenthesis, and the ) to close the group is missing. /$pat2/ is equivalent to /(\\)/ which is open-group, backslash, close-group.

| improve this answer | |
3

When you assign to $pat, the first backslash escapes the second, so the resulting string only contains one backslash. When the regex is processed, this then escapes the closing parenthesis, leaving no un-escaped parenthesis to close the capturing group.

That is to say, m// only interprets the backslashes once, but they're also interpreted within '...', so in total they're processed twice.

$ cat p.pl 
$pat = '(\\)'; print $pat
$ perl -l p.pl 
(\)

From the manual:

Quote-Like Operators
q/STRING/
'STRING'
A single-quoted, literal string. A backslash represents a backslash unless followed by the delimiter or another backslash, in which case the delimiter or backslash is interpolated.

(Of course, this is different from how backslashes and single-quotes work in the shell.)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.