0

我正在尝试解析 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 配置中提取所有键值对吗?

4

1 回答 1

1

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 循环,您可以遍历组

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
于 2017-08-08T19:57:14.520 回答