我想要一个匹配字符串'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)
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)
这是贾斯汀的想法的修订版:
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.我不确定哪个版本会更快.
| 归档时间: |
|
| 查看次数: |
771 次 |
| 最近记录: |