我怎样才能使我的Perl正则表达式仅在$ 1< $ 2〜

时间:2014-05-28 07:44:15

标签: regex perl

我不能完全开始工作的部分是有条件的,因为它总是失败:

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' );

输出

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.

2 个答案:

答案 0 :(得分:11)

您的代码需要以下修复:

  • 使用实验(?{ })代码块中的$1$2变量。
  • 需要反转您的测试以匹配您想要失败的内容。
  • 您需要阻止回溯,如果代码块指示失败,您不希望它匹配将传递的子字符串,例如在第二次测试中6小于23。有两种方法可以防止这种情况:
    • 添加单词边界,使正则表达式与部分数字不匹配。
    • 使用(*SKIP)控件动词来明确阻止回溯。

代码:

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' );

输出:

1..2
ok 1 - should match
ok 2 - should not match

答案 1 :(得分:3)

虽然米勒的解决方案完全符合您的要求 - 完全在正则表达式匹配中执行检查 - 如果我没有提出更合理的解决方案,我会失职:-)不要做这只有一个正则表达式!

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');

这更清晰,更简单,而且可能更快!

1..2
ok 1 - should match
ok 2 - should not match