如何使用 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
我需要匹配从 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