Регулярные выражения
710 сообщений
#17 лет назад
Может кто чего умного подскажет? 
Интересует возможность написать регулярку для следующей задачи: из кода
<div class="a">
<div class="b">
<div class="c">
текст
</div>
</div>
</div>
вытащить код
<div class="b">
<div class="c">
текст
</div>
</div>
Причем, вместо
<div class="c">
текст
</div>
может стоять все, что угодно (тоесть привязаться к внутреннему содержанию блока не получится).
3562 сообщения
#17 лет назад
|<div class="a">.?(<div class="b">.?<div class="c">*?</div></div>)</div>|is
Если текст.
|<div class="a">.?(<div class="b">.?<div class="c">.*?</div>.?</div>).?</div>|is
Если что угодно.
Не забываем про экранирование.
710 сообщений
#17 лет назад
SmartDesign, не, не то имелось ввиду. Я в первом посте написал, что привязаться к внутреннему содержанию нельзя (не известна внутренняя вложенность блоков div в блоке div class="b"
276 сообщений
#17 лет назад
А где регулярными пользуешься?Вот пример на php.
$matches - то что ищешь.
Или непременно надо сразу регуляркой только то что нужно вытащить ?
<?php
$text = "<div class=\"a\">\r\n<div class=\"b\">\r\n<div class=\"c\">\r\nтекст\r\n</div>\r\n</div>\r\n</div>\r\n";
preg_match_all("/<div*>(.*)<\/div>/is",$text,$matches);
print "<textarea style=\"width:1000px;height:800px\">";
print_r($matches);
print "</textarea>";
?>
78 сообщений
#17 лет назад
Надо вытащить внутренний div 1-го уровня вложенности? Не указан язык. Если это Перл, то для этого есть динамические регекспы, которые разбирают произвольный уровень вложенности. На ссылка есть курс моих лекций по рег. выражениям Перл, в них есть этот раздел и примеры. А на books.ru продаётся моя книжка по этим лекциям. (Это так, в кач. саморекламы :-).Если что, пиши на wait4sleeprambler.ru (если это надо для Перла!).
276 сообщений
#17 лет назад
Ну или, если всегда class="a":
"/(?<=(<div class=\"a\">)).*(?=<\/div>)/is"
Выражение не учитывает возможность отсутствия кавчек или лишних пробелов..... Но ИМХО это уже не сложно
710 сообщений
#17 лет назад
voral, эээхххх, тоже не подходит. Если в конец добавить лишние </div>, то будет резаться по ним, чего не требуется.Serg31416, к сожалению php5.
Придется видимо отдельную функцию писать.
276 сообщений
#17 лет назад
Стоп, что значит лишние?Поясни.... Проблему лишних можно решить. Только поясни, что ты понимаешь в данном примере под лишними?
Нужно чтоб было в результате одинаковое кол-во открывающих и закрывающих тегов?
Или ты имеешь ввиду что нужный блок может находится внутри более старшего блока? Тогда это тоже решается. Только необходимо пройтись от самого старшего. Легче всего рекурсией.
Ну на крайняк собираешь в массив все открывающие теги с позицией и закрывающие.... Но это уже больше php.
276 сообщений
#17 лет назад
Рекурсия. Делаешь пердыдущим выражение preg_match_all. Потом той же функциий каждый элемент в полученном массиве.... И так пока есть чего обрабатывать.Второй вариант идти с самого глубокого уровня вложенности на верх по <div.*</div> (не разрешая встречаться открывающим и закрывающим внутри). С модификатором жадности. И постепенно заменяя "выкушенные куски" на временные переменные
710 сообщений
#17 лет назад
voral, спасибо за интерес к вопросу. Но рекурсия - это слишком долго. Скорее соберу позиции тегов в массив и пройдусь по нему. 
5 сообщений
#17 лет назад
А здесь нужен именно RegExp? Может быть, лучше использовать что-то наподобие DOM-парсера или XPath?
710 сообщений
#17 лет назад
Scratch, а они разве сработают с невалидным кодом?
1410 сообщений
#17 лет назад
/<div class=\"a\">(*.?)<\/div>/i
Если я правильно понял задачу автора - то это должно помогать.
276 сообщений
#17 лет назад
Чем это отличается от моего предложения (кроме выражения в скобках) ?И что означает последовательность *.?
* - 0 или более раз {0,}
. -любой символ
? - 0 или 1 раз {0,1}
Наверное все же .* достаточно? Или я не допонял мысль
5 сообщений
#17 лет назад
SolNikolay, XPath не должен бы.А вот Dom parser частенько работает (по крайней мере тот который в PHP)
Вот, например:
$doc = new DOMDocument();
$doc->loadHTML("<html><body>Test<br></body></html>");
echo $doc->saveXML();
Посмотрите что он отдает -- валидный XHTML (XML). Который уже как вам угодно, парсером (или не выдавая -- через DOMXPath).
5 сообщений
#17 лет назад
Цитата ("ArtLab"):/<div class=\"a\">(*.?)<\/div>/i
Если я правильно понял задачу автора - то это должно помогать.
Под этот паттерн подходит
<div class="a">
<div class="b">
<div class="c">
текст
</div>
(т.к. нежадный .* останавливается на первом же </div>

Кстати, там закралась ошибка.

А если внутри этого "текст" находится еще один вложенный div... то вообще порвется.
3562 сообщения
#17 лет назад
Цитата ("SolNikolay"):SmartDesign, не, не то имелось ввиду. Я в первом посте написал, что привязаться к внутреннему содержанию нельзя (не известна внутренняя вложенность блоков div в блоке div class="b". Лучше всего конечный результат можно представить так: открываем xml файл в IE и сворачиваем произвольный item. Он сворачивается полностью, вне зависимости от наличия внутри таких же блоков с теми же именами.
Так все-таки что нужно сделать? Выбрать содержимое верхних/нижних уровней вложенности дивов?
710 сообщений
#17 лет назад
SmartDesign, надо выбирать полностью блок html, вне зависимости от внутреннего и внешнего окружения.К примеру из кода
<div class="a">
<div class="b">
<div class="c">
текст
</div>
</div>
</div>
<div class="a">
<div class="c">
еще текст
</div>
</div>
<div>
<div>
и еще текст
</div>
</div>
Вытащить блок
<div class="b">
<div class="c">
текст
</div>
</div>
или чуть подправив туже регулярку из того же кода вытащить
<div>
и еще текст
</div>
О DOM-парсере, XPath и SAX тоже думал, но думаю это все же медленнее, нежели регулярка. Вообще это и должно быть похоже на разбор xml через регулярные выражения.
3562 сообщения
#17 лет назад
ИМХО это не стоит делать чисто регулярками.Делаем функцию которая будет считать вложенность блоков и запоминать текст который расположен внутри блока с вложенностью = 1.
Для этого понадобится 2 регулярки.
1 - определяет начало блока
2 - определяет конец блока.
710 сообщений
#17 лет назад
Цитата ("SmartDesign"):ИМХО это не стоит делать чисто регулярками.
Делаем функцию которая будет считать вложенность блоков и запоминать текст который расположен внутри блока с вложенностью = 1.
Для этого понадобится 2 регулярки.
1 - определяет начало блока
2 - определяет конец блока.
Ну вот сейчас так и делаю, определяя позиции через preg_split. Хотя понадобится еще регулярка (функция), что бы переходить к номеру необходимого блока (просто для <div class="a"> и <div> функция определения начала блока должна быть одинаковая).