поэтому у меня есть пара файлов Nagios CFG для служб, хостов, контактов и т. д.
Я хочу проанализировать эти файлы CFG с PHP для обработки данных.
ContactGroups.CFG
define contactgroup {
contactgroup_name VAP3
alias VAP3_PRE
members userz, userw }
define contactgroup {
contactgroup_name VAP4
alias VAP4_PUSH
members userx, usery }
Services.CFG
define service {
host_name HostA
service_description HostA_HD
contact_groups VAP2,VAP3 }
define service {
host_name HostB
service_description HostB_HD
contact_groups VAP3,VAP4 }
Поэтому я хочу разобрать это как:
contactgroup_name[0] = "VAP3";
alias[0] = "VAP3_PRE";
members [0] = "userz,userw";
contactgroup_name[1] = "VAP4";
alias[1] = "VAP4_PUSH";
members [1] = "userx, usery";
И для файла служб:
host_name [0] = "HostA";
service_description [0] = "HostA_HD";
contact_groups [0] = "VAP2,VAP3";
host_name [1] = "HostB";
service_description [1] = "HostB_HD";
contact_groups [1] = "VAP3,VAP4";
Так что я могу легко справиться с этим в своем PHP-скрипте, например, в массивах, это всего лишь пример файлов CFG, они содержат больше, чем эти три определения … Может быть, с помощью regex или preg_match …?
почти в каждом полусложном языке (в данном случае в вашей конфигурации) синтаксический анализ с помощью регулярных выражений, которые соответствуют более чем одному токену, имеет некоторые крайние случаи, когда он завершится неудачно.
Предположим, вы примете наивный подход и проанализируете определение объекта с помощью
/define\s+([^\s]+){([^}]*)}/
это будет соответствовать каждой предоставленной вами контактной группе или предоставленному сервису и введет тип \1
и содержание в \2
, Однако, если есть #
спереди, вам придется отфильтровать это. Так что вы, вероятно, должны циклически перебирать все строки и удалять строки комментариев, до вы начинаете сопоставлять определения объектов.
После этого вы заметите, что есть больше комментариев, например, ; comment
так что вы бы тоже отфильтровали. Я не знаю много о разрешенных символах, но если какое-то значение может где-то содержать }
ты в беде.
Если это не так, вы, вероятно, могли бы использовать первое предоставленное регулярное выражение, а не разбивать содержимое на строки и preg_split
каждая строка внутри определения объекта с
/^\s*([^\s]+)\s+(.*)$/
где ключ в \1
и значение в \2
, но значение, вероятно, должно быть trim
редактор
Других решений пока нет …