URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID8
Нить номер: 5803
[ Назад ]

Исходное сообщение
"PHP и регулярные выражения"

Отправлено jkl , 07-Июн-08 16:00 
Доброго времени суток уважаемый all.

Возникла необходимость распарсить файл лиза dhcp.

Вид он имеет приблизительно такой:

lease 192.168.100.91 {
  starts 1 2008/04/28 11:42:29;
  ends 4 2008/05/01 11:42:29;
  binding state active;
  next binding state free;
  hardware ethernet 00:1b:38:6f:67:b1;
  uid "\001\000\0338og\261";
  client-hostname "Marlou";
}
lease 192.168.100.163 {
  starts 1 2008/04/28 19:07:36;
  ends 4 2008/05/01 19:07:36;
  binding state active;
  next binding state free;
  hardware ethernet 00:1d:60:76:32:db;
  uid "\001\000\035`v2\333";
  client-hostname "philka";
}

Каждый из таких наборов ( lease 192.168.100.163 {...} ) нужно передать в массив, из которого потом будут извлекаться для дальнейшей обработки.

В результате поисков был сделан вот такой вот код:
<?php
$menu_string = implode( "", file( "dhcpd/dhcpd.leases" ) );
preg_match_all( '/lease.*\n.*/', $menu_string, $out );
print_r( $out );
?>

Код сделан для тестов, поэтому просьба не судить строго, стажа в пхп у меня мало.

В результате работы кода я получаю на выход строку вида:

lease 192.168.100.163 {
  starts 1 2008/04/28 19:07:36;

Но это только часть того что нужно получить на выходе. Вообщем загвоздка в правильном написании регулярного выражения.

Документацию читал, но это мало что дало. Подскажите пожалуйста как это можно реализовать.


Содержание

Сообщения в этом обсуждении
"PHP и регулярные выражения"
Отправлено angra , 07-Июн-08 21:44 
/^lease\s+[\d.]+\s+{[^}]+}/
^lease - слово lease с начала строки
\s - пробельныq символ
+ повторение предыдущего символа как минимум один раз
[d.] - класс символов состоящий из цифр и .
[^}] -  класс символов состоящий из всех возможных, кроме }

Также стоит посмотреть в мане как php будет работать с многострочными скалярами, возможно понадобится дополнительная опция.


"PHP и регулярные выражения"
Отправлено jkl , 08-Июн-08 18:56 
Спасибо за ответ.

Вообщем попробовал, результат есть, но как я понял в массив помещается только первый набор данных, дальше похоже проверка не идёт. Либо как написали нужна дополнительная опция.

Если есть ещё идеи, буду признателен за помощь.


"PHP и регулярные выражения"
Отправлено jkl , 08-Июн-08 19:45 
Получилось таки.

Убрал из регулярного выражения символ ^ из /^lease\s+[\d.]+\s+{[^}]+}/ . В результате идёт поиск по всему файлу. С чем связано не могу понять.

Возможно есть мысли с чем это связано, не хочется так и остаться без понимания того как это работает :) .

Ещё раз спасибо. В основном вопрос снят.


"PHP и регулярные выражения"
Отправлено angra , 08-Июн-08 22:06 
А я ведь предупреждал :)
Связано с отсутствием опции аналогичной m(multiline) в перле. В результате ^ срабатывает на начало скаляра, а не на каждую строчку(line) в нем. Не помню я как в пыхе выставляются m,s,i,x итд, посмотрите сами в мануале.



"PHP и регулярные выражения"
Отправлено jkl , 09-Июн-08 13:57 
Нашёл я нужную опцию, если правильно понял, то конечный вид выражения такой(хотя работает что с этой опцией, что без неё):

'/(?m)lease\s+[\d.]+\s+{[^}]+}/'

Если честно читал маны и видел все эти опции не раз, но чтобы собрать их именно в таком порядке...

После решения первого вопроса возникло ещё несколько :) .
Теперь нужно распарсить некоторые строки в каждом элементе массива. Например из такого вот куска

lease 192.168.100.163 {
  starts 1 2008/04/28 19:07:36;
  ends 4 2008/05/01 19:07:36;
  binding state active;
  next binding state free;
  hardware ethernet 00:1d:60:76:32:db;
  uid "\001\000\035`v2\333";
  client-hostname "philka";
}

нужно вынуть три строки, а именно:

1 lease 192.168.100.163 {
2 hardware ethernet 00:1d:60:76:32:db;
3 client-hostname "philka";

при чём на выходе по каждой строке должно получиться следующее:

1 192.168.100.163
2 00:1d:60:76:32:db
3 philka

Для чего это нужно? Эти данные будут загоняться в хтмл-форму <select> после этого будут пересылаться другому скрипту на выполнение.

Вот код который допустим вынимает ип-адрес:

$dhcp_file = implode( "", file( "dhcpd/dhcpd.leases" ) );
preg_match_all( '/lease\s+[\d.]+\s+{[^}]+}/', $dhcp_file, $out_main );

print ( "<select name=dhcp_ip_select>\n" );
print ( "<option value=\"-1\">\n" );
foreach ( $out_main as $out_main_lvl1 )
{
    foreach ( $out_main_lvl1 as $out_main_lvl2 )
    {
        preg_match_all( '/lease\s+[\d.]+\s+/', $out_main_lvl2, $out_ip );
        foreach ( $out_ip as $out_ip_lvl1 )
    {
        foreach ( $out_ip_lvl1 as $out_ip_lvl2 )
        {
            print ( "<option value=".$out_ip_lvl2.">".$out_ip_lvl2."\n" );
        }
        }
    }
}
print ( "</select>\n" );

Недостаток в том что на выходе получаю не только ип-адрес, но весь кусок строки вида "lease 192.168.100.163".

Если поможете правильно описать и эти куски, то буду весьма признателен :).


"PHP и регулярные выражения"
Отправлено jkl , 09-Июн-08 15:04 
Первые два выражения сделал, не совсем красиво, но работает:

для ип-адреса /\s+\d+\.\d+\.\d+\.\d+/
для мак-адреса /\s+[0-h][0-h]\:[0-h][0-h]\:[0-h][0-h]\:[0-h][0-h]\:[0-h][0-h]\:[0-h][0-h]/

С именем хоста сложнее, не за что зацепиться, всё портит вот эта строка:

uid "\001\000\035`v2\333";

по виду похожа на:

client-hostname "philka";