如何使用 perl 正则表达式匹配可变长度数字范围 0 到 $n?

How to match variable length number range 0 to $n using perl regex?

我需要匹配从 0 到数字 $n 的数字范围,其中 $n 可以是 1 - 40 之间的任意随机数。

例如, 如果$n = 16,我只需要严格匹配0-16的数字范围。

我试过 m/([0-9]|[1-3][0-9]|40)/ 但匹配所有 0-40。有没有办法使用正则表达式匹配从 0 到 $n ?

为上下文附加了代码片段。

$n = getNumber();                #getNumber() returns a random number from 1 to 40.
$answer = getAnswer();           #getAnswer() returns a user input.

#Check whether user enters an integer between 0 and $n
if ($answer =~ m/regex/){
   print("Answer is an integer within specified range!\n");
}

我知道可以做类似的事情

if($answer >= 0 && $answer <=$n)

但我只是想知道是否有正则表达式的方法?

您可以动态创建模式。我在这里使用了一个非捕获组 (?:) 来将字符串锚点的开始和结束保留在 |-ed 数字列表之外。

my $n = int rand 40;
my $answer = 42;

my $pattern = join '|', 0 .. $n;

if ($answer =~ m/^(?:$pattern)$/) {
    print "Answer is an integer within specified range";
}

请记住,就您的目的而言,这没有什么意义。

如果有另一种合理的方法来解决问题,我不会拿出下面的技巧。例如,Matching Numeric Ranges with a Regular Expression.

(?(...)true|false) 构造就像一个正则表达式条件运算符,您可以使用其中一个正则表达式动词 (*FAIL) 始终使子模式失败。

条件可以用(?{...})作为条件:

my $pattern = qr/
    \b                       # anchor somehow
    (\d++)                   # non-backtracking and greedy
    (?(?{  > 42 })(*FAIL))
    /x;

my @numbers = map { int( rand(100) ) } 0 .. 10;

say "@numbers";

foreach my $n ( @numbers ) {
    next unless $n =~ $pattern;
    say "Matched $n";
    }

这是一个运行:

74 69 24 15 23 26 62 18 18 43 80
Matched 24
Matched 15
Matched 23
Matched 26
Matched 18
Matched 18

当条件复杂时,这很方便。

我之所以考虑这一点,是因为它是 Raku 中的一项鼓励功能(我在 Learning Perl 6 中有几个示例)。下面是一些形式相同的 Raku 代码,模式语法明显不同:

#!raku

my $numbers = map { 100.rand.Int }, 0 .. 20;

say $numbers;

for @$numbers -> $n {
    next unless $n ~~ / (<|w> \d+: <?{ $/ <= 42 }>) /;
    say $n
    }

结果是一样的:

(67 43 31 41 89 14 52 71 48 64 5 21 6 31 44 27 39 94 78 15 39)
31
41
14
5
21
6
31
27
39
15
39