需要帮助解析思科输出

时间:2016-06-22 05:00:23

标签: python regex parsing ciscoconfparse

我在尝试解析路由器的mrib表时遇到了一些问题。我已经能够解析其中一些但有问题。例如,我有以下输出:

(192.168.1.1,232.0.6.8) RPF nbr: 55.44.23.1 Flags: RPF
  Up: 4w1d
  Incoming Interface List
    TenGigE0/0/0/1 Flags: A, Up: 4w1d
  Outgoing Interface List
    TenGigE0/0/0/10 Flags: A, Up: 4w1d

(192.168.55.3,232.0.10.69) RPF nbr: 66.76.44.130 Flags: RPF
  Up: 4w1d
  Incoming Interface List
    TenGigE0/0/0/0 Flags: A, Up: 4w1d
    TenGigE0/1/0/0 Flags: A, Up: 4w1d
    TenGigE0/2/0/0 Flags: A, Up: 4w1d
  Outgoing Interface List
    TenGigE0/0/0/10 Flags: A, Up: 4w1d
    TenGigE0/3/0/0 Flags: A, Up: 4w1d
    TenGigE0/4/0/0 Flags: A, Up: 4w1d

我正在尝试使用上面的输出构建数据结构。为清楚起见,我希望它看起来像这样:

{'192.168.1.1,232.0.6.8': {'incoming': ['TenGigE0/0/0/1'],
                           'outgoing': ['TenGigE0/0/0/10']}}

以上听起来很简单。我遇到的主要问题之一是第二块。我试图想办法在Incoming和Outgoing接口之后迭代接口。

不一定要求代码,但这样做的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

好吧,如果您能够在Python中使用较新的regex module,则可以定义子模式并使用以下方法:

  1. 在开头
  2. 中定义IP地址的子模式
  3. ...以及传入和传出接口
  4. 分开解析接口
  5. 请参阅a demo on regex101.com
  6. <小时/>

    定义子模式

    定义IncomingOutgoing Interface字符串,IP adress和结尾的子模式。

    (?(DEFINE)
        (?<ips>[^()]+)
        (?<incoming>Incoming\ Interface \ List)
        (?<outgoing>Outgoing\ Interface \ List)
        (?<end>^$|\Z)
    )
    

    将正则表达式放在一起

    将IP部分锚定到该行的开头,并使用带有负向前瞻淬火贪心令牌作为传入/传出部分。

        ^\((?P<ip>(?&ips))\)
        (?:(?!(?&incoming))[\s\S]+?)
        (?&incoming)[\r\n]
        (?P<in>(?!(?&outgoing))[\s\S]+?) # tempered greedy token
        (?&outgoing)[\r\n]
        (?P<out>(?!^$)[\s\S]+?)
        (?&end)
    

    解析传入/传出部分

    由于您只需要接口类型/名称,您可以简单地提出:

    TenGig\S+ # TenGig, followed by anything NOT a whitespace
    

    提示

    你真的不需要定义子模式,但是你需要自己重复一遍(因为看看。看看)。因此,如果您需要坚持使用原始re模块,那么您也可以使用它。

    粘在一起

    所有在代码中粘在一起,这将是:

    import regex as re
    
    string = """
    (192.168.1.1,232.0.6.8) RPF nbr: 55.44.23.1 Flags: RPF
      Up: 4w1d
      Incoming Interface List
        TenGigE0/0/0/1 Flags: A, Up: 4w1d
      Outgoing Interface List
        TenGigE0/0/0/10 Flags: A, Up: 4w1d
    
    (192.168.55.3,232.0.10.69) RPF nbr: 66.76.44.130 Flags: RPF
      Up: 4w1d
      Incoming Interface List
        TenGigE0/0/0/0 Flags: A, Up: 4w1d
        TenGigE0/1/0/0 Flags: A, Up: 4w1d
        TenGigE0/2/0/0 Flags: A, Up: 4w1d
      Outgoing Interface List
        TenGigE0/0/0/10 Flags: A, Up: 4w1d
        TenGigE0/3/0/0 Flags: A, Up: 4w1d
        TenGigE0/4/0/0 Flags: A, Up: 4w1d
    """
    
    rx = re.compile(r"""
                (?(DEFINE)
                    (?<ips>[^()]+)
                    (?<incoming>Incoming\ Interface \ List)
                    (?<outgoing>Outgoing\ Interface \ List)
                    (?<end>^$|\Z)
                )
                ^\((?P<ip>(?&ips))\)
                (?:(?!(?&incoming))[\s\S]+?)
                (?&incoming)[\r\n]
                (?P<in>(?!(?&outgoing))[\s\S]+?)
                (?&outgoing)[\r\n]
                (?P<out>(?!^$)[\s\S]+?)
                (?&end)
    """, re.MULTILINE|re.VERBOSE)
    
    rxiface = re.compile(r'TenGig\S+')
    
    result = dict()
    for match in rx.finditer(string):
        key = match.group('ip')
        incoming = rxiface.findall(match.group('in'))
        outgoing = rxiface.findall(match.group('out'))
    
        result[key] = {'incoming': incoming, 'outgoing': outgoing}
    
    print result
    # {'192.168.1.1,232.0.6.8': {'outgoing': ['TenGigE0/0/0/10'], 'incoming': ['TenGigE0/0/0/1']}, '192.168.55.3,232.0.10.69': {'outgoing': ['TenGigE0/0/0/10', 'TenGigE0/3/0/0', 'TenGigE0/4/0/0'], 'incoming': ['TenGigE0/0/0/0', 'TenGigE0/1/0/0', 'TenGigE0/2/0/0']}}
    

答案 1 :(得分:0)

假设您的输入完整且格式正确:

matcher = re.compile(
    r'\((?P<range>[^\)]+)\)|'
    r'(?P<incoming>\s+Incoming Interface List)|'
    r'(?P<outgoing>\s+Outgoing Interface List)|'
    r'\s+(?P<interface>TenGigE0[^\s]+)'
)

with open('router_table.txt', 'r') as f:
    routing_table = []
    current_range = ''
    direction = ''
    for line in f:
        match = matcher.search(line)
        if match:
            if match.group('interface'):
                routing_table[-1][current_range][direction].append(match.group('interface'))
            if match.group('range'):
                current_range = match.group('range')
                routing_table.append(
                    {
                        current_range: {
                            'incoming': [],
                            'outgoing': []
                        }
                    }
                )
            if match.group('incoming'):
                direction = 'incoming'
            if match.group('outgoing'):
                direction = 'outgoing'