什么 Perl 正则表达式可以验证代表保龄球得分的字符串?

rol*_*eet 5 regex perl

我有代表保龄球得分的字符串:

X-91-55-72-X-X-X-90-82-91X
Run Code Online (Sandbox Code Playgroud)

我想使用 perl 正则表达式来验证该字符串是否有效。我想检查以下内容:

  1. 框架由破折号 ( -) 分隔。必须有 10 帧。

  2. 第 1 到 9 帧必须是一个罢工(单个X)或两个数字加起来不超过 10。

  3. 第 10 帧有很大不同。一些有效值如下:

    • XXX- 三击
    • XX7- 两次敲击和 0 到 9 的数字
    • X91- 一个罢工和两位数字加起来不超过 10
    • 90 - 两位数字之和小于 10
    • 91X- 两位数字相加等于 10,然后击中
    • 917- 两位数字相加等于 10,后跟一位数字 0-9

虽然我可以编写大量代码来测试每种情况,但我确信可能有一两个正则表达式可以验证字符串。我的大脑根本无法将自己包裹在正则表达式解决方案中。任何帮助表示赞赏。

以下代码验证字符串中的有效字符:

if ($gs =~ /\A[X,0-9,-]+\z/) { $valid = 1; }

我只是不知道如何验证框架

Gro*_*obu 4

这可能不是很优雅,但它的价值在于,这里有一个可能满足您需求的片段:

use constant RE_LT10      => '(?:0[0-9]|1[0-8]|2[0-7]|3[0-6]|4[0-5]|5[0-4]|6[0-3]|7[0-2]|8[0-1]|90)';

use constant RE_MAX10     => '(?:0[0-9]|1[0-9]|2[0-8]|3[0-7]|4[0-6]|5[0-5]|6[0-4]|7[0-3]|8[0-2]|9[01])';

use constant RE_IS10      => '(?:19|28|37|46|55|64|73|82|91)';

use constant RE_LASTFRAME => "(?:XXX|XX[0-9]|X${\RE_MAX10}|${\RE_LT10}|${\RE_IS10}X|${\RE_IS10}\[0-9\])";

sub is_valid
 {
 return $_[0] =~ m/^(?:(?:X|${\RE_MAX10})-){9}${\RE_LASTFRAME}\z/;
 }

my $scores = 'X-91-55-72-X-X-X-90-82-91X';
say "\$scores is $scores";
say is_valid($scores) ?1:0;
Run Code Online (Sandbox Code Playgroud)

根据 markalex 的评论,编辑了我的答案以考虑潜在的“0[0-9]”分数。