我在使用正则表达式验证用户输入时遇到了困难。我正在尝试接受用户输入并确保它在1到99之间。如果不是,那么它会调用相同的子例程,直到匹配验证条目。但是,即使输入在1-99之间,它也会继续调用子程序。
sub get_age
{
print "Age :";
@get_age = <STDIN>;
if (scalar @get_age !~ m/\d[1-99]/ ) #making sure age given is between 1 and 99
{
print "ERROR, invalid input\n";
&get_age; #this is callng the same sub it's in to re-run validating
}
push(@get_age, <STDIN>); #taking name from user and putting it in @get_name array
chomp(@get_age); #erasing newline from input
}
答案 0 :(得分:4)
您似乎对此感到困惑
@
sigil在Perl中的作用,<...>
的行为取决于上下文。&foo
)。@
sigil @
表示一个数组。这会在作业的右侧强加列表上下文。
字符类用方括号表示,并且可以包括字符范围,例如[0-9]
- 匹配阿拉伯数字。 \d
命名的字符类匹配更多字符 - 无论Unicode是什么“数字”。
使用主插入符号可以取消字符类。例如。 [^0-9]
匹配任何非阿拉伯数字的字符。
Perl运算符的行为因上下文而异。例如,readline运算符:
遇到@array
时,它会在列表上下文中计算所有元素的列表。但是,在标量上下文中,它的计算结果为 length 。
@get_age = <STDIN>
做什么因为LHS是一个数组,所以在列表上下文中评估RHS。如上所述,这将读取输入直到流耗尽。 @get_age
中的每个元素在赋值后都保留一行输入。
scalar @get_age !~ m/\d[1-99]/
做什么此表达式与
类似my $length = scalar @get_age;
not $length =~ /\d[1-9]/;
即。标量上下文中的数组求值为数组的长度,即输入中的行数。
正则表达式说“在字符串内部,必须有一个unicode数字字符后跟1,2,3,4,5,6,7,8或9”。将丢弃多次出现的charclass中的字符。该字符串可以包括任意其他字符。这应匹配:"my age is 020!"
sub get_age {
print "Age: ";
my $age = <STDIN>; # scalar context, and put into a private variable
chomp $age; # remove newline
if( not length $age ) { # check for empty string
say "You didn't type anything. Retry!";
return get_age();
}
if( $age =~ /[^0-9]/ ) { # recurse on any non-digits
say "You typed non-numeric characters. Restrict yourself to '0' through '9'. Retry!";
return get_age();
}
unless( 1 <= $age && $age <= 99 ) { # check for correct bounds
say "Valid ages have to be in the range 1 to 99. Retry!";
return get_age();
}
return $age;
}
然后在你的主要代码中:
my $age = get_age();
答案 1 :(得分:2)
#!/usr/bin/env perl
use 5.012;
use strict; use warnings;
use Term::Prompt qw( prompt );
my $age = prompt(s => 'Age:', 'between 1 and 99', '', sub {
my ($input) = @_;
($input) = ($input =~ /\A\s*( [1-9] [0-9]? )\s*\z/x);
return $input and ($input >= 1) and ($input <= 99);
}
);
say $age;
答案 2 :(得分:1)
[1-99]
是从1到9和字符9的所有字符的集合。
请尝试使用[1-9]|([1-9]\d)
。这意味着1-9或任何两个不以零开头的数字。
答案 3 :(得分:1)
我认为这是您代码的改进版本:
use strict;
use warnings;
sub get_age_and_name
{
my $age;
while(1) {
print "Age : ";
$age = <STDIN>;
chomp $age;
# Making sure age given is between 1 and 99
last if( $age =~ m/^\d\d?$/ and ($age>=1) and($age<=99) );
print "Error ERROR, invalid input\n";
}
print "Name : ";
my $name = <STDIN>;
chomp $name;
return ($age, $name);
}
my ($age, $name) = get_age_and_name;
print "($age, $name)\n";