使用 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
我正在尝试解析 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