Python - 阅读特定的文本行

Python - Read Specific Lines of Text

我正在尝试搜索文件中的特定文本。然后打印该行之前的行,以及所有以特定字符开头的后续行,尤其是 'space.'

这是我尝试读取的文件示例:

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 address'时,我想打印之前的行,然后打印该界面下的所有配置项。

目前,我正在从文件目录中读取并从文件中输出特定信息。这是代码:

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 行中声明 "interface",所以这就是我不想搜索该文本的原因,并且不能保证感叹号会是最后一项,尽管它是极有可能。这就是为什么我正在寻找一种方法来读取基于 'IP address' 和空格的行。

我对 Python 和一般编程还是个新手,但看起来 this 之类的东西可能会有帮助。我只是不完全理解它是如何工作的。

有什么想法可以实现吗?另外,我正在尝试使用 Python 3.x.

使用 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']}

编辑: 关于你的附加问题,阅读模块的文档和教程可能是明智的,其中包含 how to search for entries with specific children 的示例.要实现您的要求,您可以修改以上内容以使用 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”的接口的结果无效