Вы смешиваете синтаксис Python (логические операторы or
и |
побитовое ИЛИ) с синтаксисом регулярных выражений.
В то время как регулярные выражения используют |
для разделения альтернативных шаблонов, синтаксис, используемый в регулярных выраженияхвыражения отличаются и отделены от операторов Python.Вы не можете произвольно объединить два.Синтаксис регулярного выражения передается функциям модуля re
через строки, а не как выражения Python.
Это работает:
either = r"({}|{})\.(\d+)".format(date28, date29)
res = re.search(either, date)
, поскольку шаблон регулярного выражения объединяется в одну строку с помощьюсинтаксис регулярного выражения first .
Обратите внимание, что здесь нет смысла в использовании date28
, поскольку все, с чем date28
может совпасть, также может соответствоватьdate29
.Более того, date28
не будет соответствовать 02.19.
, действительной дате в феврале.
Если вы хотите создать регулярное выражение из «помеченных» компонентов, я рекомендую использовать флаг re.VERBOSE
, который вызываетпробел в регулярном выражении (включая новые строки), который следует игнорировать, и добавляет поддержку для использования # ...
комментариев.Для сопоставления пробелов используйте явные классы, такие как [ ]
, [\n]
, \s
и т. Д. Я часто комбинирую это и с явными именами групп.
Например, ваше выражение может быть записано как:
february_date = re.compile(
r"""
(
02\. # month, always February
( # Leap year
0[1-9] # first 9 days
|
[12][0-9] # remainder from 10 to 29
)
|
02\.
( # regular year
0[1-9] # first 9 days
|
[12][0-8] # remainder 10-18, 20-28
)
)
\.(\d+) # The year
""", flags=re.VERBOSE)
res = february_date.search(date)
Этот формат также значительно упрощает проверку соответствия 02\.
в начале любого шаблона, что довольно избыточно, и, конечно, в приведенном выше шаблоне все еще есть проблема с [12][0-8]
в обоих случаях.будучи избыточным по отношению к [12][0-9]
и фактически не совпадающим с 19 февраля.
Лично я бы просто использовал \d{2}\.\d{2}\.\d{4}
, а затем datetime.strptime()
, чтобы проверить, что сопоставленный текстна самом деле действительная дата.Создание регулярного выражения для проверки дат - гигантская задача, которая просто не стоит усилий.
Например, шаблон, который вы пытались построить, не говорит о том, что 2001 год не был високосным, поэтому 02.29.2001
недействительная датаНо попытка разобрать его с помощью datetime.strptime()
выдает исключение, сообщая, что это недопустимая дата:
>>> from datetime import datetime
>>> date = '02.29.2001'
>>> datetime.strptime(date, "%m.%d.%Y")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/_strptime.py", line 458, in _strptime
datetime_date(year, 1, 1).toordinal() + 1
ValueError: day is out of range for month