简体   繁体   English

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

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

I need to match a numeric range from 0 to a number $n where $n can be any random number from 1 - 40.我需要匹配从 0 到数字 $n 的数字范围,其中 $n 可以是 1 到 40 之间的任何随机数。

For example, if $n = 16, I need to strictly match only the numeric range from 0-16.例如,如果 $n = 16,我只需要严格匹配 0-16 的数字范围。

I tried m/([0-9]|[1-3][0-9]|40)/ but that is matching all 0-40.我试过m/([0-9]|[1-3][0-9]|40)/但这匹配所有 0-40。 Is there a way to use regex to match from 0 to $n?有没有办法使用正则表达式从 0 匹配到 $n?

The code snippet is attached for context.代码片段附在上下文中。

$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");
}

I know can probably do something like我知道可能会做类似的事情

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

But I am just wondering if there is a regex way of doing it?但我只是想知道是否有正则表达式的方式来做到这一点?

I wouldn't pull out the following trick if there's another reasonable way to solve the problem.如果有另一种合理的方法来解决问题,我不会使用以下技巧。 There is, for instance, Matching Numeric Ranges with a Regular Expression .例如,将数值范围与正则表达式匹配

The (?(...)true|false) construct is like a regex conditional operator, and you can use one of the regex verbs, (*FAIL) , to always fail a subpattern. (?(...)true|false)构造类似于正则表达式条件运算符,您可以使用正则表达式动词之一(*FAIL)来始终使子模式失败。

For the condition, you can use (?{...}) as the condition:对于条件,您可以使用(?{...})作为条件:

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

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

say "@numbers";

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

Here's a run:这是一个运行:

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

This is handy when the condition is complex.当条件复杂时,这很方便。

I only think about this because it's an encouraged feature in Raku (and I have several examples in Learning Perl 6 ).我之所以考虑这一点,是因为它是 Raku 中受鼓励的功能(我在Learning Perl 6中有几个示例)。 Here's some Raku code in the same form, and the pattern syntax is significantly different:下面是一些相同形式的 Raku 代码,模式语法明显不同:

#!raku

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

say $numbers;

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

The result is the same:结果是一样的:

(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

You can dynamically create the pattern.您可以动态创建模式。 I've used a non-capture group (?:) here to keep the start and end of string anchors outside the list of |我在这里使用了一个非捕获组(?:)将字符串锚点的开始和结束保留在|列表之外。 -ed numbers. -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";
}

Please keep in mind that for your purpose this makes little sense.请记住,出于您的目的,这没有什么意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM