如何将Cisco IOS输出解析为对象或JSON

时间:2015-08-20 19:12:10

标签: python json cisco-ios

现在,我可以使用简单的re.split("\n([^\s])", data)获得我想要的几乎所有内容,如下所示,但问题是结果列表包含单个非空白字符匹配,因为它在列表中是自己的项目。脚本下面的示例输出。注意“VLAN”中的“V”是如何被捕获到它自己的项目中的?

我也想知道是否有更好的方法可以做到这一点,也许我可以包含的库处理将表格数据转换为字典或其他东西。

#!/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

输出:

  

['','V','LAN Name Status Ports',' - ',   '--- -------------------------------- ---------   -------------------------------','1','默认有效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']

谢谢!

编辑 lines = re.findall(".*[^\n\W]*", data)似乎可能是一种更好的方法(nm无效,对不起)但是整个事情仍然感觉非常hacky所以我很乐意听到任何其他建议。

5 个答案:

答案 0 :(得分:1)

NTC Templates提供了一组模板来解析各种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']
    }
]
>>> 

答案 1 :(得分:0)

这可能不是最好的方法,但它至少是一种解决方案。使用正则表达式模块而不是re模块。

drawLine()

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

参考文献:

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

假设您的CLI cmd为

“显示界面XXXXXXXXXXX”。

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

“显示界面XXXXXXXXXXX | json-print”

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

output = json.loads(输出)

希望这会有所帮助。

答案 4 :(得分: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'}]]]

请注意组中的最后一行,它的前导空格应与要解析的实际文本的数量完全相同。