Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get my Perl regex to match only if $1 < $2?

Tags:

regex

perl

The part that I can't quite get to work is the conditional as it's always failing:

use Test::More tests => 2;

my $regex = qr/(\d+),(\d+)
               (?(?{\g1<\g2})(*FAIL))
              /x ;

  like( "(23,36)", $regex, 'should match'     );
unlike( "(36,23)", $regex, 'should not match' );

Output

not ok 1 - should match
#   Failed test 'should match'
#   at - line 7.
#                   '(23,36)'
#     doesn't match '(?^x:(\d+),(\d+)
#                    (?(?{\g1<\g2})(*FAIL))
#                   )'
ok 2 - should not match
# Looks like you failed 1 test of 2.
like image 332
Zaid Avatar asked May 28 '14 07:05

Zaid


People also ask

What is the meaning of $1 in Perl regex?

$1 equals the text " brown ".

What does $1 do in regex?

The $ number language element includes the last substring matched by the number capturing group in the replacement string, where number is the index of the capturing group. For example, the replacement pattern $1 indicates that the matched substring is to be replaced by the first captured group.

How do I match a number in Perl?

Digit \d[0-9]: The \d is used to match any digit character and its equivalent to [0-9]. In the regex /\d/ will match a single digit.


1 Answers

Your code needs the following fixes:

  • Use the $1 and $2 variables in the experimental (?{ }) code block.
  • Need to invert your test to match what you want to fail.
  • You need to prevent backtracking where if the code block indicates a failure, you don't want it to match a substring that will pass, such as 6 is less then 23 in the second test. There are two methods to prevent this:
    • Add word boundaries so the regex can't match a partial number.
    • Use the (*SKIP) control verb to prevent backtracking explicitly.

The code:

use strict;
use warnings;

use Test::More tests => 2;

my $regex = qr/(\d+),(\d+)
               (?(?{$1 > $2})(*SKIP)(*FAIL))
              /x ;

  like( "(23,36)", $regex, 'should match'     );
unlike( "(36,23)", $regex, 'should not match' );

Outputs:

1..2
ok 1 - should match
ok 2 - should not match
like image 53
Miller Avatar answered Sep 17 '22 22:09

Miller