2

Right now, I can get nearly what I want with a simple re.split("\n([^\s])", data) as shown below, but the problem is that the resulting list contains the single non-whitespace character match as it's own item in the list. Example output below script. Notice how the "V" in "VLAN" has been captured into this as it's own item?

I'm wondering also if there's just a better way to do this, perhaps a library I can include that handles converting tabular data into a dictionary or something.

#!/usr/bin/python
import re
import sys

data = """
VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
1    default                          active    Fa0/2, Fa0/3, Fa0/4, Fa0/5, Fa0/6, Fa0/7
                                                Fa0/8, Fa0/9, Fa0/10, Fa0/11, Fa0/12
                                                Fa0/13, Fa0/14, Fa0/15, Fa0/16, Fa0/17
                                                Fa0/18, Fa0/19, Fa0/20, Fa0/21, Fa0/22
                                                Fa0/23, Fa0/24, Gi0/2
1002 fddi-default                     act/unsup
1003 token-ring-default               act/unsup
1004 fddinet-default                  act/unsup
1005 trnet-default                    act/unsup
"""

lines = re.split("\n([^\s])", data)
print lines

Output:

['', 'V', 'LAN Name Status Ports', '-', '--- -------------------------------- --------- -------------------------------', '1', ' default active Fa0/2, Fa0/3, Fa0/4, Fa0/5, Fa0/6, Fa0/7\n
Fa0/8, Fa0/9, Fa0/10, Fa0/11, Fa0/12\n
Fa0/13, Fa0/14, Fa0/15, Fa0/16, Fa0/17\n
Fa0/18, Fa0/19, Fa0/20, Fa0/21, Fa0/22\n
Fa0/23, Fa0/24, Gi0/2', '1', '002 fddi-default
act/unsup', '1', '003 token-ring-default act/unsup', '1', '004 fddinet-default act/unsup', '1', '005 trnet-default act/unsup\n']

Thanks!

Edit: lines = re.findall(".*[^\n\W]*", data) seems like it's probably a better approach (nm that doesn't work, sorry) but this whole thing still feels pretty hacky so I'd love to hear any alternative suggestions.

4

5 回答 5

3

NTC 模板提供了一组模板来解析各种 Cisco IOS 命令输出(和其他网络设备)。模板与TextFSM一起进行实际的解析。

例如:

>>> from ntc_templates.parse import parse_output
>>> vlan_output = (
        "VLAN Name                             Status    Ports\n"
        "---- -------------------------------- --------- -------------------------------\n"
        "1    default                          active    Gi0/1\n"
        "10   Management                       active    \n"
        "50   VLan50                           active    Fa0/1, Fa0/2, Fa0/3, Fa0/4, Fa0/5,\n"
        "                                                Fa0/6, Fa0/7, Fa0/8\n"
    )
>>> vlan_parsed = parse_output(platform="cisco_ios", command="show vlan", data=vlan_output)
>>> vlan_parsed
[
    {
        'vlan_id': '1',
        'name': 'default',
        'status': 'active',
        'interfaces': ['Gi0/1']
    },
    {
        'vlan_id': '10',
        'name': 'Management',
        'status': 'active',
        'interfaces': []
    },
    {
        'vlan_id': '50',
        'name': 'VLan50', 'status': 'active',
        'interfaces': ['Fa0/1', 'Fa0/2', 'Fa0/3', 'Fa0/4', 'Fa0/5', 'Fa0/6', 'Fa0/7', 'Fa0/8']
    }
]
>>> 
于 2019-08-26T07:42:37.490 回答
0

我在 Mellanox 交换机(类似于 Cisco CLI)中的命令输出有类似的问题。但我使用以下方法解决了:

假设您的 CLI cmd 是

“显示接口 XXXXXXXXXXX”。

输出将采用文本格式。您可以直接以 json 格式获取输出,如下所示:

“显示接口 XXXXXXXXXX | json-print”

在您的 python 脚本中,一旦您在变量中获得命令输出,就说“输出”。您可以将其转换为 json 对象,如下所示:

输出 = json.loads(输出)

希望这可以帮助。

于 2019-04-17T11:02:23.077 回答
0

解析它并转换为结构化数据的另一种方法。

Template Text Parser可以帮助生成您需要的结果,示例代码:

from ttp import ttp
from pprint import pprint

template = """
<input load="text">
VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
1    default                          active    Fa0/2, Fa0/3, Fa0/4, Fa0/5, Fa0/6, Fa0/7
                                                Fa0/8, Fa0/9, Fa0/10, Fa0/11, Fa0/12
                                                Fa0/13, Fa0/14, Fa0/15, Fa0/16, Fa0/17
                                                Fa0/18, Fa0/19, Fa0/20, Fa0/21, Fa0/22
                                                Fa0/23, Fa0/24, Gi0/2
1002 fddi-default                     act/unsup
1003 token-ring-default               act/unsup
1004 fddinet-default                  act/unsup
1005 trnet-default                    act/unsup
</input>

<group>
{{ vid | DIGIT | _start_ }}  {{ name }}   {{ status }}
{{ vid | DIGIT | _start_ }}  {{ name }}   {{ status }}    {{ ports | ORPHRASE | replace(" ", "") | split(",") | joinmatches() }}
                                                {{ ports | ORPHRASE | replace(" ", "") | split(",") | joinmatches() }}
</group>
    """

parser = ttp(template=template)
parser.parse()
pprint(parser.result())

# Prints:
# [[[{'name': 'default',
#     'ports': ['Fa0/2',
#               'Fa0/3',
#               'Fa0/4',
#               'Fa0/5',
#               'Fa0/6',
#               'Fa0/7',
#               'Fa0/8',
#               'Fa0/9',
#               'Fa0/10',
#               'Fa0/11',
#               'Fa0/12',
#               'Fa0/13',
#               'Fa0/14',
#               'Fa0/15',
#               'Fa0/16',
#               'Fa0/17',
#               'Fa0/18',
#               'Fa0/19',
#               'Fa0/20',
#               'Fa0/21',
#               'Fa0/22',
#               'Fa0/23',
#               'Fa0/24',
#               'Gi0/2'],
#     'status': 'active',
#     'vid': '1'},
#    {'name': 'fddi-default', 'status': 'act/unsup', 'vid': '1002'},
#    {'name': 'token-ring-default', 'status': 'act/unsup', 'vid': '1003'},
#    {'name': 'fddinet-default', 'status': 'act/unsup', 'vid': '1004'},
#    {'name': 'trnet-default', 'status': 'act/unsup', 'vid': '1005'}]]]

注意 group 中的最后一行,它应该有确切数量的前导空格作为要解析的实际文本。

于 2020-08-06T08:54:48.967 回答
0

这可能不是最好的方法,但至少是一种解决方案。使用 regex 模块而不是 re 模块。

lines = regex.split("\n(?=[^\s])", data)

与内置的 re 模块不同,regex 模块允许在零宽度匹配上进行拆分,因此您可以使用前瞻在下一个字符匹配的位置进行拆分。

参考:

于 2015-08-20T21:15:14.540 回答
0

这些天来,我建议查看一个专门的现有库来进行解析。我发现的一个这样的示例库是ciscoconfparse,它将 IOS 配置(和其他一些配置)解析为行对象,这些对象维护对配置操作有用的子/父行关系。

于 2019-02-12T20:34:44.230 回答