Я настраиваю этот отрывок 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, и т.д...., что дает?
Если вам действительно нравится использовать Regex, вам нужно поставить ^ и $, как
»^ (0? [1-9] | 1 [012]) $"
Это не будет совпадать 13, 14 ....
Не используйте регулярные выражения.
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);
Вы не должны использовать регулярное выражение, чтобы сделать валидацию числового диапазона. Регулярное выражение, которое вы хотите:
/^(\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])$/
^
и $
закрепляют поиск на начало и конец строки, соответственно.
Чтобы дать вам номер оттуда - номер месяц «120» также совпадает в вашей версии: -)
Изменение:
my $month = "(0[1-9]|1[012])";
на
my $month = /^(0[1-9]|1[012])$/;
, а затем играйте больше с ним
Вот один из способов
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: