A regular expression with an expression inside curly braces does not work as expected

I am trying to understand why Perl does not seem to evaluate the expression inside curly braces, which are used to determine a certain number of events in a match:

with expression:

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

without expression:

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

I resorted to using a separate variable. What am I missing here? Thank you ... FIRST MAIL!

+5
source share
3 answers

The variable interpolation in a regular expression is similar to the interpolation variable in a string. It does not evaluate the entire string as an expression, as much as is necessary to fill the variable. Try the following:

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

and you will see what happens in your regular expression. $a is replaced, but +1 remains. And /x{1+1}/ not equivalent to /x{2}/ .

Your approach to using a separate variable is the one I would use. But there are other possibilities, such as

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

The shell ${\(...)} makes the expression the same for interpolation. But it is ugly. Another version is to do this as an array with @{[...]} as follows:

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

I think both of them are uglier than

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

In the first regular expression {} curls do not represent a quantifier, but literal characters. + is still a quantifier (doesn’t perform the addition as you expect) and will match $a 1 or many times, so the regular expression is set to match strings like

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

Exit

 b{222221} 

See perlre :

{n, m} n and m are bounded by non-negative integral values ​​less than the specified limit defined during the construction of perl.

+1
source

Variables are replaced in regular expressions, as you found with your second command, but this is not a standard regex compiler function for executing code. However, there is an experimental feature (at least, I think, that it is still experimental), which allows this:

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

More information on this can be found in perldoc , but note that it has limitations . Personally, I would be wary of this if someone else tried to save the code and did not know about this function.

Edit: single? the version of the embedded code was wrong, and the updated version is ugly (even if you had to remove it)! Proceed with updating the variable outside the regular expression and keep readability!

+1
source

Source: https://habr.com/ru/post/1209551/


All Articles