Как я могу использовать регулярное выражение для проверки ввода месяца? - PullRequest
14 голосов
/ 26 января 2010

Я настраиваю этот пример фрагмента 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, но когда я изменяю регулярное выражение на:

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

тогда регулярное выражение разрешает 13, 14 и т. Д ... что дает?

Ответы [ 9 ]

32 голосов
/ 26 января 2010

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

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

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

18 голосов
/ 26 января 2010

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

/^(\d+)$/

Тогда

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

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

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

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

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

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

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

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

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

4 голосов
/ 26 января 2010

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

Измените:

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

на

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

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

2 голосов
/ 26 января 2010

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

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);
1 голос
/ 05 января 2016

"^(1[012]|0?[1-9])$" было бы лучше, потому что регулярное выражение оценивается первым первым. Допустим, вы хотите соответствовать «12» и напишите "^(0?[1-9]|1[012])$", тогда будет выбрано «1», потому что сначала берется 0?[1-9].

0 голосов
/ 23 января 2018

Для проверки month / year:

^(0?[1-9]|1[012])\/([2-9][0-9)]{3})$
0 голосов
/ 12 ноября 2014

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

Пареньс, так что вы можете использовать это внутри другого блока, например, если соответствует весь формат даты гггг-ММ-дд

источник: http://www.regular -expressions.info / date.html

0 голосов
/ 03 января 2014
[^d>12|d<0] OR ^[d>12|d<0]
0 голосов
/ 26 января 2010

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

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:
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...