Michael Quaranta
Michael Quaranta

Reputation: 118

Perl regex with expression inside curly braces not working as expected

I'm trying to understand why Perl doesn't seem to evaluate an expression within curly braces that are used to define a specific number of occurances in a match:

with expression:

$ perl -e '$a=2;print "abbbc" =~ m/b{$a+1}/ ? "match\n" : "no match\n";'
no match

without an expression:

$ perl -e '$a=3;print "abbbc" =~ m/b{$a}/ ? "match\n" : "no match\n";'
match

I've resorted to using a separate variable. What am I missing here? Thanks... FIRST POST!

Upvotes: 6

Views: 551

Answers (3)

user2404501
user2404501

Reputation:

Variable interpolation in a regexp is like variable interpolation in a string. It doesn't evaluation the whole string as an expression, just as much as is necessary to complete a variable. Try this:

$a = 3;
print "{$a+1}\n";

and you'll see what's happening in your regexp. The $a is substituted and the +1 remains as a +1. And /x{1+1}/ is not an equivalent for /x{2}/.

Your approach of using a separate variable is the one I'd use. But there are other possibilities, like

$a = 3;
print "{${\($a+1)}}\n";
print "yes\n" if "abbbbc" =~ /ab{${\($a+1)}}c/;

The ${\(...)} wrapper makes the expression a single unit for interpolation. But it's ugly. Another version of that is to do it as an array with @{[...]} like this:

$a = 3;
print "yes\n" if "abbbbc" =~ /ab{@{[$a+1]}}c/;

I think both of those are uglier than

$a = 3;
$aplus1 = $a + 1;
print "yes\n" if "abbbbc" =~ /ab{$aplus1}c/;

Upvotes: 3

chooban
chooban

Reputation: 9256

Variables are replaced within regular expressions, as you've found with your second command, but it's not a standard feature of the regex compiler to execute code. However, there is an experimental feature (at least, I think it's still experimental), which does allow this:

perl -e '$a=2;print "abbbc" =~ m/^a(??{"b\{".($a+1)."\}"})c$/ ? "match\n" : "no match\n";'

You can find more information on that in the perldoc, but note that it has its limitations. Personally, I'd be wary of it in case anyone else tried to maintain the code and wasn't aware of the feature.

Edit: The single ? version of embedded code was not correct, and the updated version is plug ugly (even if you were to tidy it up)! Go with updating the variable outside of the regex and keep things readable!

Upvotes: 1

mpapec
mpapec

Reputation: 50637

In first regex, {} curlies are not representing quantifier but literal chars. + is still quantifier (not performing addition as you're expecting) and will match $a 1 or many times, so regex is set to match strings like,

perl -e '$a=2;print "ab{222221}bbc" =~ /(b{$a+1})/'

output

b{222221}

See perlre:

{n,m} n and m are limited to non-negative integral values less than a preset limit defined when perl is built.

Upvotes: 1

Related Questions