Регулярками занялся не так давно, поэтому испытываю трудности, а задача есть вполне конкретная. Итак:
имеется некий набор тегов типа
[tag name="name1" arg="asdf"]
всякие данные1
[tag name="name2" arg="asdf"]
всякие данные2
[tag name="name3" arg="asdf"]
всякие данные3
[/tag]
[/tag]
[tag name="name4" arg="asdf"]
всякие данные4
[/tag]
[/tag]
требуется извлечть все вложенные "теги" и получить следующий массив:
array(0) = "[tag name="name1" arg="asdf"]
всякие данные1
[/tag]
";
array(1) = " [tag name="name2" arg="asdf"]
всякие данные2
[/tag]";
array(2) = " [tag name="name3" arg="asdf"]
всякие данные3
[/tag]";
array(3) = " [tag name="name4" arg="asdf"]
всякие данные4
[/tag]";
Проблема в том, что нужно начинать извлекать сначала самые вложенные теги, то есть те, внутри которых нет "[/tag]". Так вот как мне записать выражение? с помощью [^]] глупо, так как попадись в данных "]" все собъется и тег не будет найден, а пишу (.+)(?![/tag]) находит только внешние теги :(
полное регулярное выражение которым ищу вложенные теги:
$regul = '/\[tag\s+name\s?=\s?"([^"]+)"[^\]]*\](.+)(?!\[\/tag\])\[\/tag\]/is';
выручайте, уже долго бьюсь, никак не могу найти решение :(
Спустя 47 минут, 15 секунд (27.11.2010 - 12:25) DySprozin написал(а):
хм... интересная задачка (; как-то так это работает:
$str = '
[tag name="name1" arg="asdf"]
всякие данные1
[tag name="name2" arg="asdf"]
всякие данные2
[tag name="name3" arg="asdf"]
всякие данные3
[/tag]
[/tag]
[tag name="name4" arg="asdf"]
всякие данные4
[/tag]
[/tag]
';
$str = preg_match_all('#(\[tag[^\]]*\].*)(?=\[/?tag[^\]]*\])#isU', $str, $buf);
for ($i=0; $i<count($buf[1]); $i++)
{
echo $buf[1][$i]."[/tag]<br>";
}
Спустя 14 минут, 26 секунд (27.11.2010 - 12:39) konstantin82 написал(а):
Гениально )
просто не брать в расчет закрывающий тег )))
просто не брать в расчет закрывающий тег )))
Спустя 31 минута, 16 секунд (27.11.2010 - 13:10) DySprozin написал(а):
konstantin82
ну ведь работает
ну ведь работает
![laugh.gif](http://phpforum.ru/html/emoticons/laugh.gif)
Спустя 17 минут, 26 секунд (27.11.2010 - 13:28) konstantin82 написал(а):
Цитата (DySprozin @ 27.11.2010 - 17:10) |
konstantin82 ну ведь работает :lol: |
Почти ) но не страшно, я суть уловил, а этот код выдает такой результат (речь об одном вложенном теге):
[tag name="name2" arg="asdf"]
всякие данные2
[tag name="name3" arg="asdf"]
всякие данные3
то есть он все же не учитывает возможности попадания внутрь еще одного открывающего тега. Пробую вставлять отрицание типа (?!\[tag[^]]])(?=\[\/tag[^]]]) но все равно открывающий тег захватывается :(
Объясни пож-ста смысл U в конце выражения, что то не могу найти инфу про этот модификатор
Спустя 2 минуты, 11 секунд (27.11.2010 - 13:30) konstantin82 написал(а):
Цитата (konstantin82 @ 27.11.2010 - 17:28) | ||
Почти ) но не страшно, я суть уловил, а этот код выдает такой результат (речь об одном вложенном теге):
то есть он все же не учитывает возможности попадания внутрь еще одного открывающего тега. Пробую вставлять отрицание типа (?!\[tag[^]]])(?=\[\/tag[^]]]) но все равно открывающий тег захватывается :( Объясни пож-ста смысл U в конце выражения, что то не могу найти инфу про этот модификатор |
А все, нашел : модификатор “нежадности” - Ungreedy:
Спустя 58 минут, 15 секунд (27.11.2010 - 14:28) DySprozin написал(а):
konstantin82
теперь все работает? (;
теперь все работает? (;
Спустя 4 минуты, 12 секунд (27.11.2010 - 14:33) konstantin82 написал(а):
пока нет ))) че то я запутался )
как только разберусь напишу рабочий пример, если не забуду
как только разберусь напишу рабочий пример, если не забуду
Спустя 2 минуты, 37 секунд (27.11.2010 - 14:35) DySprozin написал(а):
;;пока нет ))) че то я запутался )
чего должно отображаться и чего отобрадается? (;
чего должно отображаться и чего отобрадается? (;
Спустя 17 часов, 4 минуты, 9 секунд (28.11.2010 - 07:39) konstantin82 написал(а):
Я похоже не совсем правильно объяснил суть задачи, в общем после первого прохода по тегам должны быть выбраны только самые вложенные теги (то есть внутри них не должно быть ни одного другого тега (тем более открывающего). На данный момент пока что этого не получается. Я понял почему не срабатывает условие (?!\[tag[^]]])(?=\[\/tag[^]]]) , но в то же время пока не придумал как его правильно записать. Жаль что нельзя сделать типа [^\[\/tag\]]
это бы так пригодилось
![dry.gif](http://phpforum.ru/html/emoticons/dry.gif)
Спустя 1 час, 1 минута, 42 секунды (28.11.2010 - 08:41) DySprozin написал(а):
konstantin82
а что мешает обратить массив полученых тегов? (;
а что мешает обратить массив полученых тегов? (;
Спустя 6 часов, 56 минут, 18 секунд (28.11.2010 - 15:37) konstantin82 написал(а):
ммм..не совсем понял, это как?
Спустя 13 минут, 26 секунд (28.11.2010 - 15:51) DySprozin написал(а):
хм... ладно, покажи: что вначале имеем, что получается и что должны иметь (;
Спустя 1 час, 35 минут, 52 секунды (28.11.2010 - 17:27) konstantin82 написал(а):
Постараюсь объяснить подробнее (кстати спасибо за помощь):
Итак, вот тестовый код:
После работы скрипта получаем:
А в идеале хотелось бы получить содержимое тегов
То есть только сааамые вложенные теги из присутствующих (внутри которых нет других одноименных тегов)
Однако как видно из результата, попадаются открывающие теги...
Вот как то так.
Итак, вот тестовый код:
$str = '
[tag name="name1" arg="asdf"]
всякие данные1
[tag name="name2" arg="asdf"]
всякие данные2
[tag name="name3" arg="asdf"]
всякие данные3
[/tag]
[/tag]
[tag name="name4" arg="asdf"]
всякие данные4
[/tag]
[/tag]
';
echo 'Исходные данные:<br/>
-------------------------------------------------------------
'.nl2br(htmlspecialchars($str)).'
-------------------------------------------------------------
<br/>';
$regul = '#\[tag\s+name\s?=\s?["|\']([^"\']+)["|\'][^\]]*\](.+)(?=\[\/tag\])#isU';
//находим вложенные мультиблоки (самые самые вложенные)
$count = preg_match_all($regul, $str, $matches, PREG_SET_ORDER);
//теоритически должно получиться
//$matches[n][0] - результат с тегом [tag]
//$matches[n][1] - результат с именем name
//$matches[n][2] - результат с содержимым внутри тега
echo 'РЕЗУЛЬТАТ:<br/>
-------------------------------------------------------------
<br/>';
$i = 0;
while(isset($matches[$i])){
echo htmlspecialchars($matches[$i][0]).'<br/><br/>';
echo htmlspecialchars($matches[$i][1]).'<br/><br/>';
echo htmlspecialchars($matches[$i][2]).'<br/><br/>';
echo htmlspecialchars($matches[$i][3]);
echo '--------------------------------------------------------<br/>';
$i++;
}
После работы скрипта получаем:
Исходные данные:
-------------------------------------------------------------
[tag name="name1" arg="asdf"]
всякие данные1
[tag name="name2" arg="asdf"]
всякие данные2
[tag name="name3" arg="asdf"]
всякие данные3
[/tag]
[/tag]
[tag name="name4" arg="asdf"]
всякие данные4
[/tag]
[/tag]
-------------------------------------------------------------
РЕЗУЛЬТАТ:
-------------------------------------------------------------
[tag name="name1" arg="asdf"] всякие данные1 [tag name="name2" arg="asdf"] всякие данные2 [tag name="name3" arg="asdf"] всякие данные3
name1
всякие данные1 [tag name="name2" arg="asdf"] всякие данные2 [tag name="name3" arg="asdf"] всякие данные3
--------------------------------------------------------
[tag name="name4" arg="asdf"] всякие данные4
name4
всякие данные4
--------------------------------------------------------
А в идеале хотелось бы получить содержимое тегов
[tag name="name3" arg="asdf"]
всякие данные3
[/tag]
[tag name="name4" arg="asdf"]
всякие данные4
[/tag]
То есть только сааамые вложенные теги из присутствующих (внутри которых нет других одноименных тегов)
Однако как видно из результата, попадаются открывающие теги...
Вот как то так.
Спустя 3 часа, 9 минут, 39 секунд (28.11.2010 - 20:36) DySprozin написал(а):
konstantin82
пробуй:
B)
пробуй:
////////
////регулярка (получается с мусором, чистить его будем ниже)
$regul = '#(\[tag[^\]]+].*(?!\[tag)\[/tag\])#isU';
////
///////
$count = preg_match_all($regul, $str, $matches);
echo 'РЕЗУЛЬТАТ:<br/>
-------------------------------------------------------------
<br/>';
for ($i=0; $i<count($matches[1]); $i++) {
////////
////Чистим мусор
$regul='#\[tag.*(\[tag[^\]]+\])#isU';
$buf=$matches[1][$i];
do
$buf=preg_replace($regul,"$1",$buf,5);
while(preg_match($regul,$buf));
////
///////
echo htmlspecialchars($buf).'<br/><br/>';
}
B)
Спустя 13 часов, 5 минут, 17 секунд (29.11.2010 - 09:42) konstantin82 написал(а):
Цитата (DySprozin @ 29.11.2010 - 00:36) |
konstantin82 пробуй: //////// B) |
Хм, ну как вариант. Спасибо!