risyasin
risyasin

Reputation: 1321

PHP Regex problem with a complex target string

i need to parse dhcp leases table with php regex. but the thing is it contains different characters used in regex too.

here is sample output

lease 172.17.2.3 {
  starts 4 2009/07/16 11:54:39;
  ends 4 2009/07/16 12:54:39;
  cltt 4 2009/07/16 11:54:39;
  binding state active;
  next binding state free;
  hardware ethernet 00:50:56:c0:00:01;
  uid "\001\000PV\300\000\001";
  client-hostname "Yasin-PC";
}
lease 172.17.2.3 {
  starts 4 2009/07/16 12:24:39;
  ends 4 2009/07/16 13:24:39;
  cltt 4 2009/07/16 12:24:39;
  binding state active;
  next binding state free;
  hardware ethernet 00:50:56:c0:00:01;
  uid "\001\000PV\300\000\001";
  client-hostname "Yasin-PC";
}
lease 172.17.2.3 {
  starts 4 2009/07/16 12:54:39;
  ends 4 2009/07/16 13:54:39;
  cltt 4 2009/07/16 12:54:39;
  binding state active;
  next binding state free;
  hardware ethernet 00:50:56:c0:00:01;
  uid "\001\000PV\300\000\001";
  client-hostname "Yasin-PC";
}

problem is i want to assign whole table into an array indexed with ip addresses after lease ..XX.XX.XX.XX {... & there will be duplicate keys but values will be different so i need to solve that to...

what would you advice me to save my time to build a good regex for this ? posix or pcre or reading line by line ?

& i can not be sure about target leases table will be all in the same format. maybe some times a few more lines i expect.

Upvotes: 0

Views: 296

Answers (2)

inakiabt
inakiabt

Reputation: 1963

I think you could do this:

<?php
$order_fields = array('starts', 'ends', 'cltt', 'binding state', 'next binding state', 'hardware ethernet', 'uid', 'client-hostname');
$fields_regexp = '';
foreach ($order_fields as $field)
{
    $fields_regexp .= "\s*".$field." (.*)";
}
$regexp = '/lease (\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b) \{'.$fields_regexp.'\s*\}/m';
preg_match_all($regexp, $string, $result, PREG_PATTERN_ORDER);

$arr = array();
foreach ($result[1] as $i => $match) {
    $cont = count($arr[$match]);
    $arr[$match][$cont]['raw'] = $result[0][$i];
    $arr[$match][$cont]['ip'] = $match;
    foreach ($order_fields as $pos => $field)
    {
        $arr[$match][$cont][$field] = $result[$pos + 2][$i];
    }
}
print_r($arr);
?>

Sample Output:

Array
(
    [172.17.2.3] => Array
        (
            [0] => Array
                (
                    [raw] => lease 172.17.2.3 {
  starts 4 2009/07/16 11:54:39;
  ends 4 2009/07/16 12:54:39;
  cltt 4 2009/07/16 11:54:39;
  binding state active;
  next binding state free;
  hardware ethernet 00:50:56:c0:00:01;
  uid "�PVÀ�";
  client-hostname "Yasin-PC";
}
                    [ip] => 172.17.2.3
                    [starts] => 4 2009/07/16 11:54:39;
                    [ends] => 4 2009/07/16 12:54:39;
                    [cltt] => 4 2009/07/16 11:54:39;
                    [binding state] => active;
                    [next binding state] => free;
                    [hardware ethernet] => 00:50:56:c0:00:01;
                    [uid] => "�PVÀ�";
                    [client-hostname] => "Yasin-PC";
                )

            [1] => Array
                (
                    [raw] => lease 172.17.2.3 {
  starts 4 2009/07/16 12:24:39;
  ends 4 2009/07/16 13:24:39;
  cltt 4 2009/07/16 12:24:39;
  binding state active;
  next binding state free;
  hardware ethernet 00:50:56:c0:00:01;
  uid "�PVÀ�";
  client-hostname "Yasin-PC";
}
                    [ip] => 172.17.2.3
                    [starts] => 4 2009/07/16 12:24:39;
                    [ends] => 4 2009/07/16 13:24:39;
                    [cltt] => 4 2009/07/16 12:24:39;
                    [binding state] => active;
                    [next binding state] => free;
                    [hardware ethernet] => 00:50:56:c0:00:01;
                    [uid] => "�PVÀ�";
                    [client-hostname] => "Yasin-PC";
                )

            [2] => Array
                (
                    [raw] => lease 172.17.2.3 {
  starts 4 2009/07/16 12:54:39;
  ends 4 2009/07/16 13:54:39;
  cltt 4 2009/07/16 12:54:39;
  binding state active;
  next binding state free;
  hardware ethernet 00:50:56:c0:00:01;
  uid "�PVÀ�";
  client-hostname "Yasin-PC";
}
                    [ip] => 172.17.2.3
                    [starts] => 4 2009/07/16 12:54:39;
                    [ends] => 4 2009/07/16 13:54:39;
                    [cltt] => 4 2009/07/16 12:54:39;
                    [binding state] => active;
                    [next binding state] => free;
                    [hardware ethernet] => 00:50:56:c0:00:01;
                    [uid] => "�PVÀ�";
                    [client-hostname] => "Yasin-PC";
                )

        )

)

Upvotes: 1

Blixt
Blixt

Reputation: 50187

You could just as well parse this. Read line by line and keep current state in variables. When you hit a line with lease ... and you're not in a lease clause, set $inLease to true and handle the rest of the lines as parameters to the current lease until you hit closing brace }, and so on.

Regular expressions could help you in this case, but it won't be harder to just do simple line-by-line parsing. Considering how static the data format is, regular expressions would just be overkill for this.

Upvotes: 0

Related Questions