Проблема с регулярным выражением Python с необязательной подстрокой между ними

Ломаю голову по этому поводу уже 2 дня. Я пытаюсь сопоставить содержимое пакета с API регулярных выражений:

packet_re = (r'.*RADIUS.*\s*Accounting(\s|-)Request.*(Framed(\s|-)IP(\s|-)Address.*Attribute.*Value: (?P<client_ip>\d+\.\d+\.\d+\.\d+))?.*(Username|User-Name)(\s|-)Attribute.*Value:\s*(?P<username>\S+).*')

packet1 = """
IP (tos 0x0, ttl 64, id 35592, offset 0, flags [DF], proto UDP (17), length 213)
    10.10.10.1.41860 > 10.10.10.3.1813: [udp sum ok] RADIUS, length: 185
    Accounting-Request (4), id: 0x0a, Authenticator: 41b3b548c4b7f65fe810544995620308
      Framed-IP-Address Attribute (8), length: 6, Value: 10.10.10.11
        0x0000:  0a0a 0a0b
      User-Name Attribute (1), length: 14, Value: 005056969256
        0x0000:  3030 3530 3536 3936 3932 3536
"""
result = search(packet_re, packet1, DOTALL)

Регулярное выражение соответствует, но не может захватить Framed-IP-Address Attribute, client_ip=10.10.10.11. Дело в том, что Framed-IP-Address Attribute может или не может прийти в пакет. Следовательно, шаблон заключен в другую группу захвата, оканчивающуюся на ?, что означает 0 или 1 вхождение.

Я должен быть в состоянии игнорировать его, когда он не приходит. Следовательно, содержимое пакета также может быть:

packet2 = """
IP (tos 0x0, ttl 64, id 60162, offset 0, flags [DF], proto UDP (17), length 163)
    20.20.20.1.54035 > 20.20.20.2.1813: [udp sum ok] RADIUS, length: 135
    Accounting-Request (4), id: 0x01, Authenticator: 219b694bcff639221fa29940e8d2a4b2
      User-Name Attribute (1), length: 14, Value: 005056962f54
        0x0000:  3030 3530 3536 3936 3266 3534
"""

В этом случае регулярное выражение должно игнорировать Framed-IP-Address. Он игнорирует, но не фиксирует, когда приходит.

Похоже, вы можете использовать RADIUS.*?Accounting[\s-]Request(?:.*?(Framed[\s-]IP[\s-]Addr‌​ess.*?Attribute(?:.*‌​?Value: (?P<client_ip>\d+\.\d+\.\d+\.\d+))?))?.*User-?[nN]ame[\s-]At‌​tribute.*?Value:\s*(‌​?P<username>\S+) - regex101.com/r/HGxPzW/1. Вам не нужно .* в начале и конце, потому что даже если вам нужно, чтобы вся строка присутствовала в совпадении, вы можете использовать result.string для ее получения.

Wiktor Stribiżew 26.06.2023 09:59

Я не могу отблагодарить вас достаточно. С вашим ответом тоже есть чему поучиться. Спасибо.

tcpip 26.06.2023 10:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
2
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

я предлагаю использовать

RADIUS.*?Accounting[\s-]Request(?:.*?(Framed[\s-]IP[\s-]Address.*?Attribute(?:.*?Value: (?P<client_ip>\d+\.\d+\.\d+\.\d+))?))?.*User-?[nN]ame[\s-]Attribute.*?Value:\s*(?P<username>\S+)

Посмотрите демонстрацию регулярного выражения .

Обратите внимание, что я удалил .* на обоих концах шаблона, поскольку вы используете re.search, который не требует сопоставления в начале строки, такой как re.match, а объект MatchData содержит свойство .string, к которому вы можете получить доступ, чтобы получить всю входную строку.

Подробности

  • RADIUS - слово
  • .*? - любой ноль или более символов, как можно меньше
  • Accounting - слово
  • [\s-] - пробел или дефис
  • Request - слово
  • (?:.*? - начало необязательной группы без захвата: любой ноль или более символов как можно меньше, затем...
    • (Framed[\s-]IP[\s-]Address.*?Attribute - Группа 1: Framed + пробел или дефис + IP + пробел/дефис + Address + любой ноль или более символов как можно меньше + Attribute
      • (?:.*?Value: (?P<client_ip>\d+\.\d+\.\d+\.\d+))? - необязательная группа без захвата, соответствующая любому нулю или более символов как можно меньше + Value: + группа "client_ip": четыре шаблона соответствия одной или более цифр, разделенные буквенной точкой
    • ) - окончание группы 1
  • )? - конец внешней незахватывающей группы
  • .* - любые ноль или более символов как можно больше
  • User-?[nN]ame - Username, UserName или User-name/User-Name
  • [\s-] - пробел или дефис
  • Attribute - слово
  • .*? - любые ноль или более символов как можно меньше
  • Value: - литеральная строка
  • \s* - ноль или более пробелов
  • (?P<username>\S+) — Группа «имя пользователя»: один или несколько символов без пробелов.

Здравствуйте, @Wiktor Stribiżew, извините за ковыряние, но мне было интересно, почему это не работает: RADIUS.*?Accounting[\s-]Request(?:.*?(Framed[\s-]IP[\s-]Addr‌​ess.*?Attribute.*?Va‌​lue: (?P<client_ip>\d+\.\d+\.\d+\.\d+))?)?.*User-?[nN]ame[\s-]Att‌​ribute.*?Value:\s*(?‌​P<username>\S+) т. е. зачем нам нужна еще одна необязательная группа без захвата Value: 10.10.10.11, а не просто захват client_ip как есть.

tcpip 26.06.2023 13:15

@tcpip На самом деле, я не уверен, почему я обернул эту часть необязательной группировкой, и на самом деле, RADIUS.*?Accounting[\s-]Request(?:.*?(Framed[\s-]IP[\s-]Addr‌​ess.*?Attribute.*?Va‌​lue: (?P<client_ip>\d+\.\d+\.\d+\.\d+)))?.*User-?[nN]ame[\s-]Attr‌​ibute.*?Value:\s*(?P‌​<username>\S+)тоже работает. Ваша точка зрения не работает, потому что вы делаете только группу необязательной, но вам нужно обернуть группу И ее правую часть .*/.*? группой без захвата, чтобы заставить механизм регулярных выражений попробовать этот шаблон хотя бы один раз. .

Wiktor Stribiżew 26.06.2023 14:00

Другие вопросы по теме