PHP从文本模式生成数组(cfg文件)

so i have a couple of Nagios CFG files, for Services,Hosts,Contacts,etc

I want to parse these CFG files with PHP to handle data.

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 }

So i want to parse it like:

contactgroup_name[0] = "VAP3";
alias[0] = "VAP3_PRE";
members [0] = "userz,userw";

contactgroup_name[1] = "VAP4";
alias[1] = "VAP4_PUSH";
members [1] = "userx, usery";

And for services file:

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";

So i can handle it in my PHP script easily like arrays, these are just an example of the CFG files, they contains more than these three definitions...Maybe with a regex or preg_match...?

in almost every half-complex language (in this case your config), parsing via regular expressions that match more than one token has some edge cases where it will fail.

Assume you will take the naive approach and parse an object definition with

/define\s+([^\s]+){([^}]*)}/

this will match every contactgroup or service example you provided and put the type in \1 and the contents in \2. However, if there is a # in the front, you would have to filter that out. So you should probably cycle over all the lines and remove the comment lines, before you start matching object definitions.

After that you would notice, that there are more comments allowed, like ; comment, so you would filter that out too. I don't know much about allowed chars, but if some value somewhere may validly contain a } you're in trouble.

If that's not the case, you could probably use the first regexp provided, than split the content into lines and preg_split every line inside an object definition with

/^\s*([^\s]+)\s+(.*)$/

where the key is in \1 and the value is in \2, but the value should probably be trimed.