How can I make a Perl regex match only $ 1 <$ 2?

The part with which I cannot work normally is conditional, since it always fails:

 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. 
+6
source share
2 answers

Your code needs the following fixes:

  • Use variables $1 and $2 in the experimental block (?{ }) .
  • You need to invert your test so that it matches what you want to fail.
  • You need to prevent backtracking if the code of the code indicates a failure, you do not want it to correspond to a substring that will pass, for example, 6 less than the second in the second test. There are two ways to prevent this:
    • Add word boundaries to prevent the regular expression from matching the quotient.
    • Use the (*SKIP) control verb to prevent backtracking explicitly.

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 
+11
source

Although Millerโ€™s solution fulfills exactly what you requested, fully implement the validation according to the regular expression - I would refuse if I didnโ€™t offer a more robust solution :-) Do not do this with the usual expression!

 use strict; use warnings; use Test::More tests => 2; sub match { my $str = shift; if ($str =~ m/ (\d+) , (\d+) /x) { return $1 < $2; } return; } ok(match("(23,36)"), 'should match'); ok(!match("(36,23)"), 'should not match'); 

It is much clearer, simpler and probably faster!

 1..2 ok 1 - should match ok 2 - should not match 
+3
source

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


All Articles