使用perl regex验证数字输入

时间:2013-04-07 20:44:01

标签: regex perl validating

我在使用正则表达式验证用户输入时遇到了困难。我正在尝试接受用户输入并确保它在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
}

4 个答案:

答案 0 :(得分:4)

您似乎对此感到困惑

  1. @ sigil在Perl中的作用,
  2. 正则表达式中的字符类如何工作,
  3. Perl中的上下文是
  4. readline运算符<...>的行为取决于上下文。
  5. (为什么你永远不应该&foo)。
  6. @ sigil

    @表示一个数组。这会在作业的右侧强加列表上下文

    字符类

    字符类用方括号表示,并且可以包括字符范围,例如[0-9] - 匹配阿拉伯数字。 \d命名的字符类匹配更多字符 - 无论Unicode是什么“数字”。

    使用主插入符号可以取消字符类。例如。 [^0-9]匹配任何非阿拉伯数字的字符。

    上下文

    Perl运算符的行为因上下文而异。例如,readline运算符:

    • 标量上下文(单数)中,readline运算符读取一行,但
    • 列表上下文(复数)中,readline运算符读取所有行,直到遇到文件结尾(EOF)。要在键盘输入上发送EOF,通常使用 Ctrl - D

    遇到@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";