Python - чтение определенных строк текста
Я пытаюсь найти файлы для конкретного текста. Затем выведите строку непосредственно перед строкой и все последующие строки, которые начинаются с определенного символа, в частности с пробела.
Вот пример файла, который я пытаюсь прочитать:
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.
2 ответа
Вероятно, было бы проще использовать библиотеку разбора конфигурации 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"
)
})
Вот образец из 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'],
Вы можете использовать TTP для анализа текста выше, вот код:
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"