Как индивидуально сопоставить три отдельные части одной строки вывода CLI (LLDP) с регулярным выражением (шаблон TextFSM) - PullRequest
1 голос
/ 06 июня 2019

Я работаю с шаблонами Ansible и TextFSM (Python), чтобы динамически извлекать информацию LLDP из сетевых устройств, а затем применять вывод LLDP к тем же описаниям интерфейса устройств. В настоящее время у меня есть рабочая модель, однако мне нужно настроить то, что записано в описании интерфейса, чтобы соответствовать нашему соглашению об именах (hostname-interface), где имя хоста не может включать полное доменное имя, а интерфейс должен быть первыми тремя буквами интерфейса в нижнем case (в данном случае «eth») сразу же следует номер интерфейса (24). Конечный результат будет выглядеть как «lab-fr-sw01-eth24»

Я могу получить соответствующий штраф с (\ S +) для каждой переменной в шаблоне:

Value NEIGHBOR (\S+)
Value LOCAL_INTERFACE (\S+)   
Value NEIGHBOR_INTERFACE (\S+)

Пример вывода CLI: Et1 lab-fr-sw01.test.local Ethernet24 120

Единственная проблема с этим состоит в том, что иногда коммутатор вытягивает полное доменное имя для переменной «NEIGHBOR», как описано выше, а иногда нет. Прямо сейчас я пытаюсь написать определенный оператор регулярного выражения (шаблоны TextFSM используют только регулярное выражение) для каждой переменной. Для переменной соседа я пытаюсь сопоставить вторые непробельные символы до "." если это существует. До сих пор я был в состоянии точно захватить только локальный интерфейс (Et1) с помощью (^ \ S +), а затем, когда я пытаюсь получить только имя хоста с помощью ^ [^.] +, Я также включаю вывод локального интерфейса "Et1". Чтобы соответствовать, я использовал https://regex101.com

Et1 lab-fr-sw01.test.local Ethernet24 120

Where LOCAL_INTERFACE = Et1, --> (^\S+)
NEIGHBOR = lab-ew-sw01.test.local and --> ^[^.]+ 
NEIGHBOR_INTERFACE = Ethernet24 --> ?

Желаемый конечный результат, который будет записан в описание интерфейса устройства, будет выглядеть примерно как «lab-fr-sw01-eth24». Однако, поскольку у нас есть несколько сайтов, и каждое имя сайта включено в имя хоста, я не могу полагаться на попытку сопоставить имя хоста буква за буквой.

1 Ответ

1 голос
/ 06 июня 2019

Я предполагаю, что здесь мы хотим захватить три части нашей строки, что мы можем сделать с помощью простого выражения, такого как:

([a-z0-9]+)\s+([\w\-\.]+)\s([a-z0-9]+)\s([0-9]+)

Демо 1

, где наши желаемые выходы находятся в группах #1, #2 и #3, и здесь мы также применяем флаг i.

Test

# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility

import re

regex = r"([a-z0-9]+)\s+([\w\-\.]+)\s([a-z0-9]+)\s([0-9]+)"

test_str = "Et1 lab-fr-sw01.test.local Ethernet24 120"

subst = "LOCAL_INTERFACE = \\1\\nNEIGHBOR = \\2\\nNEIGHBOR_INTERFACE = \\3"

# You can manually specify the number of replacements by changing the 4th argument
result = re.sub(regex, subst, test_str, 0, re.MULTILINE | re.IGNORECASE)

if result:
    print (result)

# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.

Демо

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here* * 1030

Редактировать

Для захвата test.local мы просто удалили бы . из нашего списка символов:

([a-z0-9]+)\s+([\w\-]+)(.+?)\s([a-z0-9]+)\s([0-9]+)

Демо 2

...