Вы не должны использовать регулярное выражение для проверки числового диапазона. Вы хотите регулярное выражение:
/^(\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])$/
^
и $
привязывают поиск к началу и концу строки соответственно.