I'm trying to parse a Nagios / Icinga config so I can do further processing on it with Python. Since I could not find a working library to do that (pynag does not seem to work at all), I'm trying to write a simple Python script using regexes to do so.
Basically I want to get from this configfile (it uses tabs for indentation):
define host {
address 123.123.123.123
passive_checks_enabled 1
}
define service {
service_description Crondaemon
check_command check_nrpe_1arg!check_crondaemon
}
to something like this Python tuple:
(
('host', ('address', '123.123.123.123'), ('passive_checks_enabled', '1')),
('service', ('service_description', 'Crondaemon'), ('check_command', 'check_nrpe_1arg!check_crondaemon'))
)
This is my full script with parsing logic including an example to test:
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))
Unfortunately I cannot get the full parsing to work, it always matches everything or nothing. Can you please give me a hint how to fix my regex so I can extract all key value pairs from my Icinga config?
re module doesn't support repeated captures, so
'(\t(.*)?\t(.*)?\n)*'
only preserves last group capture.
Likewise I would transform this like that
'\t(\w+)\s+([^\n]*)\n\'
So a possible solution, given the structure of your data, can be creates a regular expression that will match either pattern:
regex = r'define\s+(\w+)\s+\{\n|\t(\w+)\s+([^\n]*)\n|\t\}'
matches = re.finditer(regex, TEST_STR, re.DOTALL)
With a for loop you can iterate over the groups
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