Python re.match включает необязательную группу None - PullRequest
1 голос
/ 15 апреля 2019

Я пытаюсь использовать re.compile в цикле строки.После перезапуска запускаем re.match по строкам.Используя Regex101, я получаю правильные совпадения для групп, но, работая внутри python, он возвращает None для группы с пустой строкой.То, что я ищу, - это сопоставление групп, даже если они пустые.

Строка для сопоставления:

Interface          Status      Protocol    Description
BE1                up          up          
Mg0/RSP0/CPU0/0    up          up          NNI to Cat2960x G1/0/1
Te0/0/0/3          admin-down  admin-down  
Gi0/0/1/0          down        down        Test L2VPN
RP/0/RSP0/CPU0:LAB-9001-1#

Последняя группа (описание) должна быть необязательной и может содержать описание.или быть пустым.Это работает в Regex101, и у меня есть 4 группы для этого фильтра:

^\s*(?:(?P<interface>[a-zA-Z0-9]\S+?))\s+(?:(?P<status>[up|admin\-down]\S+?))\s+(?:(?P<protocol>[up|admin\-down]\S+))\s+(?:(?P<description>(?<!^).*))

В коде, который я использую, скомпилировать и сопоставить, но если описание пустое, оно возвращает None, когда я хочу, чтобы он возвратил первые 3группы и пустая строка для 4-й группы (описание).

for line in result.splitlines():
            line = line.rstrip()

            p1 = re.compile(r'^\s*(?:(?P<interface>[a-zA-Z0-9]\S+?))\s+(?:(?P<status>[up|admin\-down]\S+?))\s+(?:(?P<protocol>[up|admin\-down]\S+))\s+(?P<description>(?<!^).*)')
            m = p1.match(line).groups()
            print(m)

это не будет совпадать с чем-либо пустым для описания.Является ли их синтаксис для указания re.match включать пустые группы?

1 Ответ

1 голос
/ 15 апреля 2019

Используемое регулярное выражение содержит классы символов вместо группирующих конструкций ([up|down] не соответствует up или down, оно соответствует u, p, |, d, o , w или n) и последняя часть шаблона должна совпадать с обязательным пробелом + любые символы, кроме вашей rstrip строки и не осталось места для совпадения.

Фиксированное регулярное выражение выглядит как

^(?P<interface>[a-zA-Z0-9]\S*)\s+(?P<status>up|admin-down)\s+(?P<protocol>up|admin-down)(?:\s+(?P<description>.*))?

См. График Regulex:

enter image description here

Подробнее

  • ^ - начало строки
  • (?P<interface>[a-zA-Z0-9]\S*) - Групповой «интерфейс»: буквенно-цифровой код с последующими 0+ непробельными символами
  • \s+ - 1+ пробелов
  • (?P<status>up|admin-down) - группа "статус": up или admin-down
  • \s+ - 1+ пробелов
  • (?P<protocol>up|admin-down) - Группа «Протокол»: up или admin-down
  • (?:\s+(?P<description>.*))? - необязательная группа:
    • \s+ - 1+ пробелов
    • (?P<description>.*) - Группа «описание»: любые 0+ символов, кроме как разрыва строки, как можно больше

В Python вы можете использовать

import re
result = r"""Interface          Status      Protocol    Description
BE1                up          up          
Mg0/RSP0/CPU0/0    up          up          NNI to Cat2960x G1/0/1
Te0/0/0/3          admin-down  admin-down  
Gi0/0/1/0          down        down        Test L2VPN
RP/0/RSP0/CPU0:LAB-9001-1#"""
p1 = re.compile(r'(?P<interface>[a-zA-Z0-9]\S*)\s+(?P<status>up|admin-down)\s+(?P<protocol>up|admin-down)(?:\s+(?P<description>.*))?')

for line in result.splitlines():
    line = line.rstrip()
    m = p1.match(line)
    if m:
        print(m.groups())

См. Демоверсию Python

Обратите внимание, что начало ^ привязки строки не обязательно, если вы используете re.match.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...