什么Perl正则表达式可以匹配连续的数字子集12345?

Jon*_*ler 6 regex perl

我想要一个匹配字符串'12345'的任何连续子集的Perl正则表达式.

我可能只是大脑冻结,但这是我的测试代码和当前最好的正则表达式.我可以看到如何通过增加替代方案来强行解决问题,但我想知道我缺少哪种优雅的选择.[ 我没有特别需要捕获数字; 我已经离开了样本正则表达式而没有非捕获括号,使其稍微不那么混乱.]

测试用例:

use strict;
use warnings;

my @good = qw( 1 12 123 1234 12345 2 23 234 2345 3 34 345 4 45 5);
my @bad  = qw( 0 6 13 134 1345 145 15 124 1245 125 1235 24 245 25
               35 21 32 43 54 543 5432 54321);

my $qr = qr/^(1?(2?(3(4(5)?)?)?)?)$/;   # 3 'good', 3 'bad' failures
#my $qr = qr/^(1?(2(3(4(5)?)?)?)?)$/;   # 6 'good' failures.
my $fail = 0;

foreach my $opt (@good)
{
    printf "GOOD %d: $opt - missed by regex\n", ++$fail if ($opt !~ /$qr/);
}

foreach my $opt (@bad)
{
    printf "BAD %d: $opt - allowed by regex\n", ++$fail if ($opt =~ /$qr/);
}

print(($fail == 0) ? "PASS\n" : "FAIL\n");
Run Code Online (Sandbox Code Playgroud)

样本输出:

案例1(已注释掉):

GOOD 1: 3 - missed by regex
GOOD 2: 34 - missed by regex
GOOD 3: 345 - missed by regex
GOOD 4: 4 - missed by regex
GOOD 5: 45 - missed by regex
GOOD 6: 5 - missed by regex
FAIL
Run Code Online (Sandbox Code Playgroud)

案例2(有效):

GOOD 1: 4 - missed by regex
GOOD 2: 45 - missed by regex
GOOD 3: 5 - missed by regex
BAD 4: 13 - allowed by regex
BAD 5: 134 - allowed by regex
BAD 6: 1345 - allowed by regex
FAIL
Run Code Online (Sandbox Code Playgroud)

那么,你能写一个很好的简单,对称的正则表达式,它匹配我想要的而不是我不喜欢的吗?


这个正则表达式允许测试用例通过,但不像我希望的那样优雅:

my $qr = qr/^((1?(2(3(4(5)?)?)?)?)|(3?(4(5)?)?)|5)$/;
Run Code Online (Sandbox Code Playgroud)

使用Justin的解决方案进行测试

use strict;
use warnings;

my @good = qw( 1 12 123 1234 12345 2 23 234 2345 3 34 345 4 45 5);
my @bad  = qw( 0 6 13 134 1345 145 15 124 1245 125 1235 24 245 25
               35 21 32 43 54 543 5432 54321 11 122 1233 1223 12234);

#my $qr = qr/^(1?(2?(3(4(5)?)?)?)?)$/;   # 3 'good', 3 'bad' failures
#my $qr = qr/^(1?(2(3(4(5)?)?)?)?)$/;    # 6 'good' failures.
#my $qr = qr/^((1?(2(3(4(5)?)?)?)?)|(3?(4(5)?)?)|5)$/;  # Passes

# Ysth's solution - passes
#my $qr = qr/^[12345](?:(?<=1)2|(?<=2)3|(?<=3)4|(?<=4)5)*$/;

my $fail = 0;

foreach my $opt (@good)
{
    printf "GOOD %d: $opt - missed by regex\n", ++$fail if ('12345' !~ /$opt/);
    #printf "GOOD %d: $opt - missed by regex\n", ++$fail if ($opt !~ /$qr/);
}

foreach my $opt (@bad)
{
    printf "BAD %d: $opt - allowed by regex\n", ++$fail if ('12345' =~ /$opt/);
    #printf "BAD %d: $opt - allowed by regex\n", ++$fail if ($opt =~ /$qr/);
}

print(($fail == 0) ? "PASS\n" : "FAIL\n");
Run Code Online (Sandbox Code Playgroud)

小智 12

反转比赛:

'12345' =~ /$opt/
Run Code Online (Sandbox Code Playgroud)


cjm*_*cjm 7

这是贾斯汀的想法的修订版:

index('12345', $opt) >= 0;
Run Code Online (Sandbox Code Playgroud)

或者,如果您需要排除空字符串

index('12345', $opt) >= 0 and length $opt;
Run Code Online (Sandbox Code Playgroud)

这样,您无需检查$opt正则表达式metachars.我不确定哪个版本会更快.