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.

Вы должны попробовать регулярное выражение для таких задач, где в строках есть шаблон. Короче говоря, ищите re модуль Python.

Paandittya 23.02.2019 01:37

Не думал об этом. Проблема здесь в том, что нет уникальных паттернов, которых нет на других линиях. Например, на коммутаторе может быть более 200 интерфейсов. Я хочу видеть только те, в которых действительно есть определенный «шаблон» или набор команд. Regex будет охватывать только построчно, не так ли?

T.J. 23.02.2019 20:11

Построчная основа — это не то, как это работает. Он работает с любым строковым объектом. Но в любом случае ответ Коди ниже - лучший путь вперед. Кстати, ciscoconfparse использует регулярные выражения, поэтому здесь наверняка есть шаблоны.

Paandittya 24.02.2019 06:37
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
492
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Вероятно, было бы проще использовать библиотеку анализа конфигурации 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, так что это может быть именно то, что нужно. Спасибо!

T.J. 23.02.2019 19:26

Так что я дал ему шанс. Похоже, это также поможет выполнить пару других целей — поиск имен VLAN и просмотр конфигураций портов доступа. Что мне нужно выяснить, чтобы выполнить мою первоначальную цель из этого поста, так это отфильтровать только интерфейсы. В большинстве конфигураций, с которыми будет работать этот скрипт, будет множество конфигураций для каждого порта доступа. Например, связующее дерево или конфигурации NAC. Если бы я работал со стеком из пяти коммутаторов, я мог бы получить на выходе 240 конфигураций интерфейса в дополнение к конфигурациям IP. Мысли?

T.J. 23.02.2019 20:07

Может быть, есть способ сказать: «Если вывод ciscoconfparse содержит« IP-адрес »или« IP-помощник-адрес », то напечатать?

T.J. 23.02.2019 20:16

Спасибо. Я еще немного почитаю из документации. Я не знал, что вы можете использовать отношения родитель/потомок с этими командами. Похоже, для того, чтобы этот компонент заработал, не потребуется много времени.

T.J. 24.02.2019 23:20

Вот образец из рекомендованного выше 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».

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