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

Parse Nagios / Icinga Config with Python Regex

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

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)))

return:

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