Я пытаюсь искать файлы для определенного текста. Затем напечатайте строку, непосредственно предшествующую этой строке, и все последующие строки, начинающиеся с определенного символа, особенно пробела.
Вот пример файла, который я пытаюсь прочитать:
interface vlan 22
ip address 10.10.2.1 255.255.255.0
ip helper-address 10.10.44.1
ip helper-address 10.10.44.2
!
interface vlan 23
ip address 10.10.23.1 255.255.255.0
ip helper-address 10.10.44.1
ip helper-address 10.10.44.2
!
Когда я вижу «IP-адрес», я хочу напечатать строку непосредственно перед этим, а затем все элементы конфигурации в этом интерфейсе.
В настоящее время я читаю из каталога файлов и вывожу конкретную информацию из файлов. Вот код:
for file in glob.glob('*.log'):
with open(file) as search:
with open(queryoutput,"a") as foutput:
for line in search:
line = line.rstrip()
if hostcheck in line:
hostentry = line.split("hostname ")[1]
foutput.write("Subnet information below is from " + hostentry + "\n")
elif ipaddress in line:
foutput.write("Local Device: " + hostentry + "\n")
foutput.write("Remote " + line + "\n")
Не все сетевые устройства будут указывать «интерфейс» в строке VLAN, поэтому я не хочу искать этот текст, и нет гарантии, что восклицательный знак будет последним, хотя это весьма вероятно. Вот почему я ищу способ читать строки на основе «IP-адреса» и пробелов.
Я все еще новичок в Python и программировании в целом, но похоже, что что-то вроде это может помочь. Я просто не совсем понимаю, как это будет работать.
Любые мысли о том, как я могу это сделать? Кроме того, я пытаюсь использовать Python 3.x.
Не думал об этом. Проблема здесь в том, что нет уникальных паттернов, которых нет на других линиях. Например, на коммутаторе может быть более 200 интерфейсов. Я хочу видеть только те, в которых действительно есть определенный «шаблон» или набор команд. Regex будет охватывать только построчно, не так ли?
Построчная основа — это не то, как это работает. Он работает с любым строковым объектом. Но в любом случае ответ Коди ниже - лучший путь вперед. Кстати, ciscoconfparse использует регулярные выражения, поэтому здесь наверняка есть шаблоны.
Вероятно, было бы проще использовать библиотеку анализа конфигурации Cisco, чем начинать с первых принципов.
Например, модуль ciscoconfparse упрощает вашу проблему, создавая словарь, в котором каждый interface
сопоставляется со списком его элементов конфигурации. Для поиска других типов объектов достаточно изменить аргумент на find_objects
.
Предполагая, что мы имеем дело с файлом с именем test-config
:
import pprint
from ciscoconfparse import CiscoConfParse
parse = CiscoConfParse("test-config", syntax = "ios")
pprint.pprint({
obj.text: [child.text.strip() for child in obj.children]
for obj in parse.find_objects(r"interface")
})
Результат:
{'interface vlan 22': ['ip address 10.10.2.1 255.255.255.0',
'ip helper-address 10.10.44.1',
'ip helper-address 10.10.44.2'],
'interface vlan 23': ['ip address 10.10.23.1 255.255.255.0',
'ip helper-address 10.10.44.1',
'ip helper-address 10.10.44.2']}
Редактировать: Что касается вашего дополнительного вопроса, вероятно, было бы разумно прочитать документацию и учебник для модуля, который содержит, среди прочего, примеры как искать записи с конкретными дочерними элементами. Чтобы добиться того, о чем вы просите, вы можете изменить приведенное выше, чтобы использовать функцию find_objects_w_child()
:
pprint.pprint({
obj.text: [child.text.strip() for child in obj.children]
for obj in parse.find_objects_w_child(
parentspec=r"^interf", childspec=r"ip .*address"
)
})
Черт... Не знал, что этот модуль существует. О результатах отпишусь здесь. Похоже, он может работать не только на IOS, так что это может быть именно то, что нужно. Спасибо!
Так что я дал ему шанс. Похоже, это также поможет выполнить пару других целей — поиск имен VLAN и просмотр конфигураций портов доступа. Что мне нужно выяснить, чтобы выполнить мою первоначальную цель из этого поста, так это отфильтровать только интерфейсы. В большинстве конфигураций, с которыми будет работать этот скрипт, будет множество конфигураций для каждого порта доступа. Например, связующее дерево или конфигурации NAC. Если бы я работал со стеком из пяти коммутаторов, я мог бы получить на выходе 240 конфигураций интерфейса в дополнение к конфигурациям IP. Мысли?
Может быть, есть способ сказать: «Если вывод ciscoconfparse содержит« IP-адрес »или« IP-помощник-адрес », то напечатать?
Спасибо. Я еще немного почитаю из документации. Я не знал, что вы можете использовать отношения родитель/потомок с этими командами. Похоже, для того, чтобы этот компонент заработал, не потребуется много времени.
Вот образец из рекомендованного выше ciscoconfparse. Это на самом деле очень полезно. Просто интересно, могу ли я как-то исключить все интерфейсы коммутатора для устройств.
'interface FastEthernet0/7': ['spanning-tree portfast'],
'interface FastEthernet0/8': ['switchport access vlan 300',
'switchport mode access',
'authentication event fail action next-method',
'authentication event server dead action reinitialize vlan 999',
'authentication host-mode multi-auth',
'authentication order dot1x mab',
'authentication priority dot1x mab',
'authentication port-control auto',
'mab eap',
'dot1x pae authenticator',
'spanning-tree portfast'],
'interface FastEthernet0/9': ['switchport access vlan 300',
'switchport mode access',
'authentication event fail action next-method',
'authentication event server dead action reinitialize vlan 999',
'authentication host-mode multi-auth',
'authentication order dot1x mab',
'authentication priority dot1x mab',
'authentication port-control auto',
'mab eap',
'dot1x pae authenticator',
'spanning-tree portfast'],
'interface GigabitEthernet0/1': [],
'interface GigabitEthernet0/2': [],
'interface Vlan1': ['no ip address', 'shutdown'],
'interface Vlan300': ['ip address 172.22.0.1 255.255.255.0',
'ip helper-address 10.208.111.196',
'ip helper-address 10.208.111.195'],
'interface Vlan310': ['ip address 172.31.200.1 255.255.255.0',
'ip access-group guest-restrictions in',
'ip helper-address 10.208.111.195',
'ip helper-address 10.208.111.196'],
'interface Vlan500': ['ip address 172.19.0.2 255.255.255.248'],
Вы можете использовать ТТП для анализа текста выше, вот код:
from ttp import ttp
data = """
interface vlan 22
ip address 10.10.2.1 255.255.255.0
ip helper-address 10.10.44.1
ip helper-address 10.10.44.2
!
interface vlan 23
ip address 10.10.23.1 255.255.255.0
ip helper-address 10.10.44.1
ip helper-address 10.10.44.2
!
interface Fast0/31
switchport
!
interface vlan 77
description Not In Use
!
"""
template = """
<group contains = "ip">
interface {{ interface | ORPHRASE }}
ip address {{ ip }} {{ mask }}
ip helper-address {{ dhcp | to_list | joinmatches }}
</group>
"""
parser = ttp(data, template)
parser.parse()
print(parser.result(format = "json")[0])
будет печатать:
[
[
{
"dhcp": [
"10.10.44.1",
"10.10.44.2"
],
"interface": "vlan 22",
"ip": "10.10.2.1",
"mask": "255.255.255.0"
},
{
"dhcp": [
"10.10.44.1",
"10.10.44.2"
],
"interface": "vlan 23",
"ip": "10.10.23.1",
"mask": "255.255.255.0"
}
]
]
TTP позволяет фильтровать результаты на основе полученных совпадений, в этом конкретном случае функция группы «содержит» делает недействительными результаты для интерфейсов, у которых нет совпадений для «ip».
Вы должны попробовать регулярное выражение для таких задач, где в строках есть шаблон. Короче говоря, ищите
re
модуль Python.