如何使用正则表达式验证月份输入?

cos*_*son 15 regex perl

我正在设置此示例Perl片段以验证日期中的几个月:

我想接受的一些场景是:

MM M

#!/usr/bin/perl
use strict;
use warnings;

my $pattern;
my $month = "(0[1-9]|1[012])";
my $day = "(0[1-9]|[12]\d|3[01])";

system("cls");

do {

    print "Enter in a month: ";
    chomp($pattern = <STDIN>);

    # We only want to print if the pattern matches
    print "Pattern matches\n" if ($pattern =~ /$month/);


} while ($pattern ne "Q");
Run Code Online (Sandbox Code Playgroud)

当我运行它时,它正确地从01-12过滤但是当我将正则表达式更改为:

$month = "(0?[1-9]|1[012])";
Run Code Online (Sandbox Code Playgroud)

然后正则表达式允许13,14等...给出了什么?

YOU*_*YOU 34

如果你真的想使用正则表达式,你需要把^和$,就像

"^(0?[1-9]|1[012])$"

它不会匹配13,14 ....

  • 模式匹配或搜索问题. (2认同)
  • 注意,这将同时匹配“ 01”和“ 1”。对于仅从SO复制和粘贴的某些人来说可能并不明显... (2认同)
  • @DanGordon 是对的。您可以将正则表达式更改为 ^(0[1-9]|1[012])$ ,这将解决问题。 (2认同)

Gre*_*ill 18

您不应使用正则表达式进行数值范围验证.你想要的正则表达式是:

/^(\d+)$/
Run Code Online (Sandbox Code Playgroud)

然后,

if ($1 >= 1 && $1 <= 12) {
    # valid month
}
Run Code Online (Sandbox Code Playgroud)

这比任何正则表达式更容易阅读以验证数值范围.

另外,Perl通过在目标中搜索匹配的表达式来评估正则表达式.所以:

/(0[1-9]|1[012])/
Run Code Online (Sandbox Code Playgroud)

搜索0后跟1到9,或1搜索后跟0,1或2.例如,这将匹配"202"和许多其他数字.另一方面:

/(0?[1-9]|1[012])/
Run Code Online (Sandbox Code Playgroud)

搜索可选的0 1到9,或1搜索后跟0,1或2.所以"13"在这里匹配,因为它包含1,匹配正则表达式的前半部分.要使正则表达式按预期工作,

/^(0?[1-9]|1[012])$/
Run Code Online (Sandbox Code Playgroud)

^$锚定搜索字符串的开始和结束,分别.

  • +1:简单数值验证的正则表达式是过度的. (3认同)
  • `/(0[1-9]|1[012])/` 不会匹配 "202",它会匹配 "2**02**" 的 02 部分,但那是完全不同的。 (2认同)

MBO*_*MBO 5

给你提示 - 月份数字“120”在你的版本中也匹配:-)

改变:

my $month = "(0[1-9]|1[012])";
Run Code Online (Sandbox Code Playgroud)

my $month = /^(0[1-9]|1[012])$/;
Run Code Online (Sandbox Code Playgroud)

然后玩更多