代码之家  ›  专栏  ›  技术社区  ›  Wolkenarchitekt

用Python正则表达式解析Nagios/Icinga配置

  •  0
  • Wolkenarchitekt  · 技术社区  · 7 年前

    我试图解析一个Nagios/Icinga配置,以便用Python对其进行进一步处理。因为我找不到一个可以工作的图书馆( pynag 我正在尝试使用正则表达式编写一个简单的Python脚本。

    define host {
        address 123.123.123.123
        passive_checks_enabled  1
        }
    
    define service {
        service_description Crondaemon
        check_command   check_nrpe_1arg!check_crondaemon
        }
    

    类似于Python元组的内容:

    (
     ('host', ('address', '123.123.123.123'), ('passive_checks_enabled', '1')), 
     ('service', ('service_description', 'Crondaemon'), ('check_command', 'check_nrpe_1arg!check_crondaemon'))
    )
    

    import re
    
    # white spaces are tabs!
    TEST_STR = """
    define host {
        address 123.123.123.123
        passive_checks_enabled  1
        }
    
    define service {
        service_description Crondaemon
        check_command   check_nrpe_1arg!check_crondaemon
        }
    """
    
    cfg_all_regex = re.compile(
        r'define\s+(\w+)\s*\{'
        '(.*?)'
        '\t}',
        re.DOTALL
    )
    # basic regex works
    print(re.findall(cfg_all_regex, TEST_STR))
    
    cfg_all_regex = re.compile(
        r'define\s+(\w+)\s*{\n'
        '(\t(.*)?\t(.*)?\n)*'
        '\t}',
        re.DOTALL
    )
    # more specific regex to extract all key values fails
    print(re.findall(cfg_all_regex, TEST_STR))
    

    不幸的是,我无法进行完整的解析,它总是匹配所有内容或什么都不匹配。 你能给我一个提示,如何修复我的正则表达式,以便我可以从我的Icinga配置中提取所有键值对吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   alvarez    7 年前

    re模块不支持重复捕获,因此

    '(\t(.*)?\t(.*)?\n)*'
    

    仅保留最后一次组捕获。

    '\t(\w+)\s+([^\n]*)\n\'
    

    因此,考虑到数据的结构,一个可能的解决方案是创建一个正则表达式,该正则表达式将匹配任何一种模式:

    regex = r'define\s+(\w+)\s+\{\n|\t(\w+)\s+([^\n]*)\n|\t\}'
    matches = re.finditer(regex, TEST_STR, re.DOTALL)
    

    for match in matches:
        for groupNum in range(0, len(match.groups())):
            groupNum = groupNum + 1
            if match.group(groupNum):
                print("Group {}: {}".format(groupNum, match.group(groupNum)))
    

    返回:

    Group 1: host
    Group 2: address
    Group 3: 123.123.123.123
    Group 2: passive_checks_enabled
    Group 3: 1
    Group 1: service
    Group 2: service_description
    Group 3: Crondaemon
    Group 2: check_command
    Group 3: check_nrpe_1arg!check_crondaemon