[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Проблема с пониманием (?!regul)
konstantin82
Здра!

Регулярками занялся не так давно, поэтому испытываю трудности, а задача есть вполне конкретная. Итак:

имеется некий набор тегов типа

[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

Спустя 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)
Цитата (DySprozin @ 27.11.2010 - 17:10)
konstantin82
ну ведь работает  :lol:

Почти ) но не страшно, я суть уловил, а этот код выдает такой результат (речь об одном вложенном теге):

[tag name="name2" arg="asdf"]
всякие данные2

[tag name="name3" arg="asdf"]
всякие данные3


то есть он все же не учитывает возможности попадания внутрь еще одного открывающего тега. Пробую вставлять отрицание типа (?!\[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 это бы так пригодилось

Спустя 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
пробуй:

////////
////регулярка (получается с мусором, чистить его будем ниже)

$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
пробуй:

////////
////регулярка (получается с мусором, чистить его будем ниже)

$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,"",$buf,5);
while(preg_match($regul,$buf));
////
///////

echo htmlspecialchars($buf).'<br/><br/>';
}

B)

Хм, ну как вариант. Спасибо!
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.