Regex Range Operator

I have the line '11 15 '. W / Regex I then compares the values ​​inside this line, in this case 11 and 15 (there can be any number of digits, but I will keep it simple with 2 double-digit numbers).

For each of these numbers, I then see if it matches any of the numbers I want; in this case, I want to see if there is a number "12", "13" or "14". If so, I am changing the value of "$ m":

my $string = '11 15 '; while ( $string =~ /([0-9]{1,})\s+/ig ) { my $m = $1; print $m . "....."; $m = 'change value' if $m =~ /[12...14]{2,}/g; print $m . "\n"; } 

It produces:

 11.....change value 15.....15 

'15 'remains the same as it should. But "11" is changing. What am I doing wrong?

+4
source share
3 answers

[12...14] matches "1", "2", "." and "4". "11" Corresponds to this; "15" - no. If you are simply matching numbers, you should not use regular expressions. Change your line to the following:

 $m = 'change value' if $m ~~ [11..14]; 

Or, if you cannot guarantee perl> = v5.10:

 $m = 'change value' if grep { $m == $_ } 11..14; 
+4
source

You misunderstood the correct expression. Where you wrote [12...14]{2,} , this means that "corresponds to 2 or more characters 1 or 2 or dot, dot or dot or dot or 1 or 4".

Try something like:

 $m='change value' if $m=~/(\d{2,})/ and $1 >= 12 and $1 <= 14; 

In the substitution operation, this can be written as:

 $m =~ s/(\d{2,})/ $1 >= 12 && $1 <= 14 ? 'change value' : $1/ge; 

That is, write down 2 or more digits, and then check what you have done to see if they are what you want to change using the Perl code in the substitution replacement section. The e modifier indicates that Perl should evaluate the replacement as Perl code.

+4
source

Rewrite the code a bit:

 my $string = '11 15 '; while ( $string =~ /(\d+)/g ) { 

I changed the regex of the while statement. You can use \d+ to represent one or more digits, and this is easier to understand than [0-9]{1,} . You also (since the space does not match \d ), you do not need the last space at the end of the line.

Take a look at the rest of the code:

 my $string = '11 15'; while ( $string =~ /(\d+)/g ) { my $match = $1; print "$match....."; if ($match >= 12 and $match <= 14) { #if ($match ~~ [12..14]) for Perl > 5.10 print 'change value\n'; } else { print "$match\n"; } } 

You cannot use regular expression the way you should test a range.

Use a regular range test instead.

 if ($match >= 12 and $match <= 14) 

or newer group test:

 if ($match ~~ [12..14]) #Note only two dots and not three! 

This last one works only in newer versions of Perl, such as 5.12 on my Mac and 5.14 on my Linux box, but not on Perl 5.8 in my Solaris window).

A few tips:

  • Use indents and spaces. This makes your code more readable.
  • Use descriptive names for variables. Instead of $m I used $match .
  • Do not use the supplied if . The attached if harder to detect, so you may miss something important, and this makes it difficult to update your code. It can be used if the report itself is clear and simple, and it improves readability. The latter is a bit subjective, but you usually see attached if in things like return if not -f $file; .
  • Save variables for one purpose. In this case, instead of changing the value of $match I used the if/else . Imagine your code was a bit more complicated and someone had to add a new function. They see the $match variable and believe that this is what they need. Sorry, you changed what $match . Now this is the value to be printed, not the string match. It may take someone who modified your program for a while to find out what happened to the value of $match and why it was mysteriously set to t219>.
  • In the print statement, you can include variables inside double quotes. This is very different from almost all other languages. This is because the Perl variable uses sigils to denote variable names. This usually makes reading easier if your combined variables and other lines are on the same line.

For instance:

  print "The range of possible values are $low to $high\n"; 

vs.

  print "The range of possible values are " . $low . " to " . $high . "\n"; 

Note that in the second example, I had to be careful with the spaces inside the quotes, while in the first example the required spaces were pretty natural. Imagine that you need to change this statement in a later version of the program. What will be easier to maintain?

0
source

All Articles