Tutorial :PHP Regex problem with a complex target string



Question:

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.


Solution:1

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


Solution:2

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.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »