【问题标题】:Using regex, get values and create dictionary使用正则表达式,获取值并创建字典
【发布时间】:2020-04-16 01:51:19
【问题描述】:

第一次发布关于 Python 的持续学习。

目前,我遇到了一件非常简单的事情:我有一个路由器的输出 - 一个名为“接口”的列表 - 打印时看起来像这样:

set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24
set interfaces ge-0/0/1 unit 0 family inet dhcp
set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30
set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30

使用 re 模块 (findall),我正在查找并匹配一些我需要的关键字,如下所示:

pattern1 = re.compile(r'ge.{1,7}')
pattern2 = re.compile(r'dhcp')
matched1 = pattern1.findall(interfaces)
matched2 = pattern2.findall(interfaces)

此时,问题是:如果此路由器输出的行(?)包含单词“dhcp”,我想保存/存储该值并获取接口名称/编号。在上面的示例中,包含“dhcp”的接口是“ge-0/0/1”。如果我走在正确的道路上,你们知道吗?

  • 模型(获取两个正则表达式)是否有用,然后将两个值合并到字典中,然后使用 return 打印?
  • 如何解析其余的路由器代码行,以查找此“dhcp”值,如果没有匹配,则返回“无”或“不存在”输出?

预期的输出将如下所示(我正在使用“返回表格”来打印输出):

| interface   | service    |
|-------------+------------|
| ge-0/0/0    |  none      | 
| ge-0/0/1    |  dhcp      | 
| ge-0/0/2    |  none      |

欢迎任何指导。 谢谢。


编辑:到目前为止,感谢您的回答。我正在添加更多信息,因为可能是关键。 我获得路由器输出的方式是使用 SaltStack 集成模块。我正在使用以下语法从 Salt Master 运行该 python 文件:

interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']['show configuration interfaces | display set']

我真诚地希望输出实际上是一个列表。

与此同时,我使用以下方法再次尝试:

def dhcp():

interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']['show configuration interfaces | display set']

pattern = re.findall(r'ge.{1,7}', interfaces)
pattern1 = re.findall(r'dhcp', interfaces)

return pattern, pattern1 

输出是这样的:

outright ~  sudo salt 'vsrx1' red.dhcp
vsrx1:
 |_
   - ge-0/0/0 
   - ge-0/0/0 
   - ge-0/0/0 
   - ge-0/0/0 
   - ge-0/0/1 
   - ge-0/0/2 
   - ge-0/0/2 
 |_
   - dhcp

单独打印列表(使用 --> return("List is: " + str(pattern)) )

 outright ~  sudo salt 'vsrx1' red.dhcp
 vsrx1:
 List is: ['ge-0/0/0 ', 'ge-0/0/0 ', 'ge-0/0/0 ', 'ge-0/0/0 ', 'ge-0/0/1 ', 'ge-0/0/2 ', 'ge-0/0/2 ']

如果表达问题的方式在技术上很差,我深表歉意。我仍在学习一般术语。

【问题讨论】:

    标签: python regex dictionary findall python-re


    【解决方案1】:

    在我看来,您似乎走在了正确的轨道上。这是我对您所要求的内容的解释。希望这可以帮助。 注意:我是通过手机完成的,所以请原谅不正确的缩进

    import re
    
    s = ["set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24",
    "set interfaces ge-0/0/1 unit 0 family inet dhcp", "set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30", 
    "set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30"]
    
    print("interfaces | services")
    mydict ={}
    def parse_addresses():
        for i in s:
                interface = re.search(r"ge.{1,7}", i)
                if "dhcp" in i:
                    service = "dhcp"
                    mydict.setdefault("router",{interface.group(): service})
                else:
                    service = "None"
                print(f"{interface.group()} | {service}")
        if bool(mydict):
            return mydict
        return "None"
    
    print(parse_addresses())
    

    【讨论】:

    • 谢谢,维克多。我添加了更多信息以避免混淆信息来源。希望你对它有另一种看法。
    【解决方案2】:

    我不确定您如何获得路由器的输出。但这应该有效 如果你的数据是这种形式

    interface_list = ['set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24',
    'set interfaces ge-0/0/1 unit 0 family inet dhcp',
    'set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30',
    'set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30']
    

    然后

    interface_dict = {}
    
    for element in interface_list:
        element_list = element.split(" ")
        if element_list[7] =='dhcp':
            interface_dict[element_list[2]] = 'dhcp'
        else:
            interface_dict[element_list[2]] = 'none'
    
    print(interface_dict)
    

    会给你

    {'ge-0/0/0': 'none', 'ge-0/0/1': 'dhcp', 'ge-0/0/2': 'none'}
    

    然后您可以将字典更改为数据框

    import pandas as pd
    
    df = pd.Series(interface_dict).to_frame().reset_index().rename(columns={'index':'interface', 0:'service'})
    
    df 
        interface   service
    0   ge-0/0/0    none
    1   ge-0/0/1    dhcp
    2   ge-0/0/2    none
    
    

    【讨论】:

    • 谢谢,@pi_pascal ,我会试试的,我会带着结果回来!
    • 感谢关于 Pandas 的建议。我把它留了一会儿,试图首先修复表的“合并”并创建我需要的字典。添加了有关路由器输出的信息。谢谢。
    【解决方案3】:

    感谢所有从几个可能的方向查看和指导我的人。 我正在回答我自己的问题(至少 90%)。我的最终脚本如下(是的,我知道我的代码可以 100% 改进,但这是我为实现目标所做的):

    def final():

    interfaces = []
    output_table1 = []
    output_table2 = []
    
    interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']['show configuration interfaces | display set']
    
    # Saving output into a file for further use
    with open("/srv/salt/_modules/aaa.txt", "w") as file:
        file.write(interfaces)
    
    # Regex patterns to match things
    regex1 = re.compile(r'(ge.{1,7}.{7}).*?(?=sampling)')
    match_reg1 = regex1.finditer(interfaces)
    
    regex2 = re.compile(r'ge.{1,7}.{7}')
    match_reg2 = regex2.finditer(interfaces)
    
    
    # IF stataments and FOR, to match and append items
    if match_reg1:
        output_table1.insert(0, "Sampled interfaces")
        for match1 in match_reg1:
            output_table1.append(match1.group(1))
    
    if match_reg2:
        output_table2.insert(0, "Not sampled interfaces")
        for match2 in match_reg2:
            output_table2.append(match2.group())
    
    # Differences between two tables: 
    difference_list = []
    for item in output_table2:
        if item not in output_table1:
            difference_list.append(item)
    
    final = []
    final.insert(0, "To enable sampling, insert the following on target device")
    for line in difference_list:
        final.append("set interfaces " + line + "family inet sampling [input/output]")
    
    return output_table1, difference_list, final
    

    在上面之后,我的输出是:

    terminal# sudo salt 'vsrx1' red.final
    vsrx1:
    |_
      - Sampled interfaces
      - ge-0/0/1 unit 0 
      - ge-0/0/1 unit 0 
    |_
      - Not sampled interfaces
      - ge-0/0/0 descrip
      - ge-0/0/0 unit 0 
      - ge-0/0/2 unit 0 
      - ge-0/0/2 unit 0 
    |_
      - To enable sampling, insert the following on target device
      - set interfaces Not sampled interfacesfamily inet sampling [input/output]
      - set interfaces ge-0/0/0 descripfamily inet sampling [input/output]
      - set interfaces ge-0/0/0 unit 0 family inet sampling [input/output]
      - set interfaces ge-0/0/2 unit 0 family inet sampling [input/output]
      - set interfaces ge-0/0/2 unit 0 family inet sampling [input/output]
    

    请记住,我正在使用 Saltstack 代理 minions 从 Juniper vSRX 设备中提取信息。我现在需要练习更多的 REGEX 来删除所有不必要的输出数据,并且更准确地了解我想要看到的内容,就像上面的示例一样(仍然很脏),但基本目标已经实现。

    一开始我遇到的另一个挑战是理解“interfaces = salt['net.cli']('show configuration interfaces...”的输出是因为我认为每个路由器命令行是我列表中的一个项目/行。将其保存在“aaa.txt”文件中然后打印它时,它的打印与我的想法不同:

    这是VisualCode打开的文件(文件名为aaa.txt):

    set interfaces ge-0/0/0 description vsrx1_descr_test
    set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24
    set interfaces ge-0/0/1 unit 0 family inet sampling input
    set interfaces ge-0/0/1 unit 0 family inet sampling output
    set interfaces ge-0/0/1 unit 0 family inet dhcp
    set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30
    set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30
    

    这是函数打印出来的文件:

    terminal# sudo salt 'vsrx1' red.final
    vsrx1:
    
    set interfaces ge-0/0/0 description vsrx1_descr_test
    set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24
    set interfaces ge-0/0/1 unit 0 family inet sampling input
    set interfaces ge-0/0/1 unit 0 family inet sampling output
    set interfaces ge-0/0/1 unit 0 family inet dhcp
    set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30
    set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30
    

    当改变 SALT 函数时:

    interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']['show configuration interfaces | display set']"
    to this:
    interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']
    

    输出是垂直打印的,如下所示:

    s
    e
    t
    
    i
    n
    t
    e
    r
    

    等等。我被那个弄坏了。

    希望这会有所帮助。与往常一样,欢迎任何更正。

    克里斯蒂安。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-13
      • 1970-01-01
      • 2021-01-07
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多