У меня нет прямого ответа на вопрос, с пустой строкой принимаются. Я не думаю, что проблема в регулярном выражении - ни в оригинале, ни в пересмотренной версии. Я думаю, что suggestion на dtanders, вероятно, находится на пути; ваши комментарии поддерживают это.
Однако, я думаю, что есть место для упрощения и улучшения вашего регулярного выражения.
В регулярном выражении много ненужных круглых скобок, и логика кажется немного запутанной. Вы проверяете 0000-00-00 (на самом деле последний вариант, но самый короткий для описания), или за «любую действительную дату в любой високосный год» или за «любую действительную дату в течение не-високосного года». Это приводит к большому повторному куску регулярного выражения для проверки всех инвариантных месяцев.
Было бы меньше повторений, если вы изменили свой код для проверки на 0000-00-00 или любого действительного дня в любом месяце или в любой действительный високосный день.
В Perl вы можете писать расширенные регулярные выражения, где пробелы не значимы, и регулярное выражение может быть распространено по многим строкам, чтобы было легче понять. Это приводит к тестовому сценарию, как:
#!/usr/bin/env perl
use strict;
use warnings;
my $rx = qr/
^(
20\d{2} -
( (0[13578] | 1[02]) - (0[1-9] | [12]\d | 3[01])
| ((0[469] | 11) - (0[1-9] | [12]\d | 30))
| (02 - (0[1-9] | 1\d | 2[0-8]))
)
| (^20[02468][048] | ^20[13579][26]) - 02 - 29 # Leap day
| 0000-00-00
)$
/x;
while (<>)
{
chomp;
printf "%s: %s\n", (m/$rx/ ? "PASS" : "FAIL"), $_;
}
Если регулярное выражение уплощена на одной линии (и комментарий удален), то вы получите:
^(20\d{2}-((0[13578]|1[02])-(0[1-9]|[12]\d|3[01])|((0[469]|11)-(0[1-9]|[12]\d|30))|(02-(0[1-9]|1\d|2[0-8])))|(20[02468][048]|20[13579][26])-02-29|0000-00-00)$
Оригинальное регулярное выражение занимает 276 символов. Пересмотр занимает 158 при сплющивании.
Я вызывал скрипт regex-hell
и создал файл various-dates
с различными образцами дат в нем. Выход был:
PASS: 0000-00-00
FAIL: 0001-00-00
FAIL: 0000-01-00
FAIL: 0000-00-01
FAIL: 2000-00-00
FAIL: 2000-01-00
FAIL: 2000-00-01
PASS: 2000-01-01
PASS: 2000-02-28
PASS: 2000-02-29
PASS: 2001-02-28
FAIL: 2001-02-29
PASS: 2003-03-31
FAIL: 2003-03-32
PASS: 2004-04-30
FAIL: 2004-04-31
PASS: 2005-05-31
FAIL: 2005-05-32
FAIL: 2005-05-00
PASS: 2005-05-01
PASS: 2006-06-30
FAIL: 2006-06-31
PASS: 2007-07-31
FAIL: 2007-07-32
PASS: 2008-08-31
FAIL: 2008-08-32
PASS: 2009-09-30
FAIL: 2009-09-31
FAIL: 2009-09-32
PASS: 2010-10-30
PASS: 2010-10-31
FAIL: 2010-10-32
PASS: 2011-11-30
FAIL: 2011-11-31
PASS: 2012-12-31
FAIL: 2012-12-32
PASS: 2099-01-01
PASS: 2099-12-31
FAIL:
Вы реализуете это на определенном языке? Очень вероятно, что вы можете обойти это с помощью функции длины строки, которая предоставляется большинством языков. – npinti
Я пишу для атрибута 'pattern'' input' HTML, это регулярное выражение хранится в переменной PHP, а затем эхо-код HTML –
Внешний '(...) {1}' бессмыслен; это означает то же, что и «...». Я надеюсь, что это часть попытки разобраться в проблеме «она соответствует пустой строке». –