Как я могу использовать регулярное выражение для проверки входа месяца?

Я настраиваю этот отрывок 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");

Когда я выполняю это, это правильно фильтрует от 01-12, но когда я изменяю regex на:

$month = "(0?[1-9]|1[012])";

затем regex позволяет 13, 14, и т.д...., что дает?

15
задан Tim Cooper 25 September 2011 в 01:52
поделиться

5 ответов

Если вам действительно нравится использовать Regex, вам нужно поставить ^ и $, как

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

Это не будет совпадать 13, 14 ....

34
ответ дан 1 December 2019 в 00:04
поделиться

Не используйте регулярные выражения.

Perl имеет возможность автоматически оценивать как число или строку на основе контекста. 01-09 будет оценивать до 1-9 в числовом контексте. Итак, вы можете просто проверить значение:

print "Enter in a month: ";
chomp($pattern = <STDIN>);
# We only want to print if the pattern matches
print "Pattern matches\n" if ($pattern < 13 && $pattern > 0);
2
ответ дан 1 December 2019 в 00:04
поделиться

Вы не должны использовать регулярное выражение, чтобы сделать валидацию числового диапазона. Регулярное выражение, которое вы хотите:

/^(\d+)$/

,

if ($1 >= 1 && $1 <= 12) {
    # valid month
}

,

if ($1 >= 1 && $1 <= 12) {
    # valid month
}

Это намного проще чтение, чем любое регулярное выражение для проверки числового диапазона.

Кроме того, Perl оценивает регулярные выражения поиском в пределах цели для соответствующего выражения. Итак:

/(0[1-9]|1[012])/

ищет 0, а затем 1-9, или A 1, а затем 0, 1, или 2. Это будет соответствовать «202», например, и многие другие номера. С другой стороны:

/(0?[1-9]|1[012])/

ищет необязательный от 0 1 до 9 или 1, а затем 0, 1 или 2. Так что «13» совпадает здесь, потому что он содержит 1, сопоставив первую половину Regeex. Чтобы ваши регулярные выражения работали, как вы ожидаете,

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

^ и $ закрепляют поиск на начало и конец строки, соответственно.

18
ответ дан 1 December 2019 в 00:04
поделиться

Чтобы дать вам номер оттуда - номер месяц «120» также совпадает в вашей версии: -)

Изменение:

my $month = "(0[1-9]|1[012])";

на

my $month = /^(0[1-9]|1[012])$/;

, а затем играйте больше с ним

4
ответ дан 1 December 2019 в 00:04
поделиться

Вот один из способов

while(1){
    print "Enter in a month: ";
    $pattern = <STDIN>;
    chomp($pattern);
    if ($pattern =~ /^(Q|q)$/ ){last;}
    if ($pattern =~ /^[0-9]$/ || $pattern =~ /^[0-9][12]$/ ) {
        print "Pattern matches\n";
    }else{
        print "try again\n";
    }
}

вывод

$ perl perl.pl
Enter in a month: 01
Pattern matches
Enter in a month: 000
try again
Enter in a month: 12
Pattern matches
Enter in a month: 00
try again
Enter in a month: 02
Pattern matches
Enter in a month: 13
try again
Enter in a month:
0
ответ дан 1 December 2019 в 00:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: