как работает оператор OR (|) в регулярном выражении? - PullRequest
0 голосов
/ 26 сентября 2019

Хотите использовать оператор or (|) в совпадении с регулярным выражением, но оно не работает.Получение сообщения об ошибке как «неподдерживаемый операнд».Может кто-нибудь, пожалуйста, посмотрите на это здесь?

Даже пробовал оба |и "или", но оба не работали.

import re

date = "02.29.2001"
date29 = "((02)\.(0[1-9]|[12][0-9]))"
date28 = "((02)\.(0[1-9]|[12][0-8]))"
res = re.search((date28 | date29)+("\.(\d+)"),date)

Здесь, если я использую только date29, тогда это совпадает, но когда я изменил его на как выше, это не совпадало.

1 Ответ

1 голос
/ 26 сентября 2019

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