Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум Регулярные Выражения

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Возможно разобрать BBCodes вложенные друг в друга?
 
 автор: MOVe   (14.11.2005 в 11:19)   письмо автору
 
 

Уважаемые, возможно ли при помощи регекспов отследить вложенность тэгов BBCode?

Например:

[quote]
  цитата
  [quote] вложенная цитата[/quote]
  [quote]
    цитата вложенная в цитату
    [quote]
  [/quote]
[/quote]


Если все тэги quote вложены правильно, то даже простейшая замена тэгов сработает замечательно. А если допущена ошибка, то весь код может пойти наперекосяк. Можно ли при помощи регулярных выражений оставить нетронутым лишний тэг quote? То же самое можно отнести и к тэгу [code] и ещё к нескольким.

Заранее спасибо, если кто поможет.
Могу написать большую программу, которая будет отслеживать уровень вложенности, но может это можно решить и при помощи регулярных выражений?

Есть идея, что можно сначала заменять все тэги [quote] [/quote] между которыми не встречается тэга [quote], но мне не реализовать это в регулярных выражениях. Я с ними пока не дружу. Могу только элементарные вещи делать. Учусь. Может конечно сам разберусь, а может и не осилю.

   
 
 автор: cheops   (14.11.2005 в 14:35)   письмо автору
 
   для: MOVe   (14.11.2005 в 11:19)
 

Здесь вот какая проблема - у вас часть тэгов вложена, а часть последовательна, т.е. первому [quote] - соответствует последний [/quote], а второму, уже не соответствует предпоследний, а соответствует третий [/quote]. Смотрите, что я имею ввиду
[quote] 
  цитата 
  [quote]
    вложенная цитата[/quote] 
    [quote] 
      цитата вложенная в цитату 
    [quote] 
  [/quote] 
[/quote]

Т.е. мы можем разобрать тэги (хоть с использованием регулярных выражений, хоть без), но либо они все будут вложенными, либо все последовательными.

   
 
 автор: MOVe   (14.11.2005 в 14:51)   письмо автору
 
   для: cheops   (14.11.2005 в 14:35)
 

Лучше, чтобы все вложенные были. То есть первый+последний, потом второй + предпоследний, а уж если будет ошибка внутри, то это просто можно будет исправить.

Если не лень, то можно оба варианта - с регекспами и без. Но меня в основном интересуют регекспы :)

Можно на "Ты" ;)
Спасибо!

P.S. Кстати, было бы неплохо, если бы количество вложений можно было ограничить :) Если это выполняется в цикле, то там без проблем. А если регекспами, то может будет возможность предусмотреть это?

   
 
 автор: Artem S.   (14.11.2005 в 20:02)   письмо автору
 
   для: MOVe   (14.11.2005 в 14:51)
 

Я бы сделал так:
- нашел первое верное вложение
- заменил его на необходимое (загнать в таблицы или слои)
- все это в цикл до последнего правильного вложения
Я тут набросал:
<?
$parrent 
"#\[quote\](?!\[quote])(?<!\[/quote\])(.*?)\[/quote\]#s";
$str "[quote]
  цитата
  [quote] вложенная цитата[/quote]
  [quote]
    цитата вложенная в цитату
    [quote]
  [/quote]
[/quote]"
;

echo 
"Оригинал: \n".$str."\n\n";

while ( 
preg_match($parrent$str) )
{
    
$str preg_replace($parrent"<div>\n$1\n</div>",  $str);
}

echo 
"Измененный: \n".$str."\n";
?>


Оригинал: 
[quote]
  цитата
  [quote] вложенная цитата[/quote]
  [quote]
    цитата вложенная в цитату
    [quote]
  [/quote]
[/quote]

Измененный: 
<div>

  цитата
  <div>
 вложенная цитата
</div>
  <div>

    цитата вложенная в цитату
    [quote]
  
</div>

</div>

   
 
 автор: MOVe   (14.11.2005 в 21:24)   письмо автору
 
   для: Artem S.   (14.11.2005 в 20:02)
 

Огромное спасибо. Работает как нужно.
Только я не понимаю как :( :cry:

Извиняюсь, что сразу не спросил.
А как сделать, чтобы тэги вида [quote="nick"] и [quote] обрабатывались одинаково?

Попробовал в условии написать следующее:
#\[quote(.*)?\](?!\[quote(.*)?])(?<!\[/quote\])(.*?)\[/quote\]#s

Но не заработало...

Так, извиняюсь за столько текста, но пытаюсь разобраться понемногу.
Вот рабочий шаблон:
#\[quote(.*?)\](?!\[quote.*?])(?<!\[/quote\])(.*?)\[/quote\]#s

Всё равно в основном ничего не понимаю :(

   
 
 автор: Artem S.   (14.11.2005 в 21:57)   письмо автору
 
   для: MOVe   (14.11.2005 в 21:24)
 

На самом деле не все так хорошо... шаблон кое как работает (не совсем так как я ожидал)

Вот попробуйте следующее
<?
$parrent 
"#\[quote(=\"[a-z]+\")?\](?!\[quote])(?<!\[/quote\])(.*?)\[/quote\]#si";
?>

   
 
 автор: MOVe   (14.11.2005 в 22:17)   письмо автору
 
   для: Artem S.   (14.11.2005 в 21:57)
 

Второе не работает. К тому же мне всё, что в кавычках =".*" тоже нужно использовать.

Не знаю в чём у Вас проблема, но у меня работает именно так, как мне и нужно было. Спасибо! В принципе ="" я попробую функцией удалить.

Что именно Вам не нравится в этом шаблоне?

   
 
 автор: MOVe   (14.11.2005 в 22:40)   письмо автору
 
   для: MOVe   (14.11.2005 в 22:17)
 

Вобщем, вот скрипт, результат которого меня полностью устраивает. Если, конечно, нет "подводных камней", которых я найти не могу:

$parrent="#\[quote=?(.*?)\](?!\[quote])(?<!\[/quote\])(.*?)\[/quote\]#si";
while(preg_match($parrent,$str))
{
$str=preg_replace($parrent,"<div id=\"quote\"><h1>Цитата: $1</h1><p>$2</p></div>\n",$str);
}

Ещё раз спасибо!

   
 
 автор: Artem S.   (14.11.2005 в 23:55)   письмо автору
 
   для: MOVe   (14.11.2005 в 22:40)
 

На самом деле подводные камни тут есть.
Скажем как такое преобразовывать?
[quote] 1 [quote] 2 [/quote]
В
<div> 1 [quote] 2 </div>
Или
[quote] 1 <div> 2 </div>

Шаблон в данном случае можно сократить до
$parrent="#\[quote=?(.*?)\](.*?)\[/quote\]#si";

   
 
 автор: MOVe   (15.11.2005 в 00:03)   письмо автору
 
   для: Artem S.   (14.11.2005 в 23:55)
 

Мне важнее, чтобы лишние тэги оставались нетронутыми, вместо того, чтобы они на весь оставшийся текст применяли какое-то свойство. Например: bold [b] - здесь важно, чтобы последнее [b] осталось нетронутым. То есть не превратилось в <b> иначе весь последующий текст будет жирным.

   
 
 автор: Artem S.   (15.11.2005 в 00:49)   письмо автору
 
   для: MOVe   (15.11.2005 в 00:03)
 

Вот! Новый шаблон. В чем разница можете посмотреть на примере.

<?
$parrent_new
"#\[quote\]((?:(?<!\[/quote\]).(?!\[quote\]))+)\[/quote\]#is";
$parrent_old "#\[quote(=\"[a-z]+\")?\](?!\[quote])(?<!\[/quote\])(.*?)\[/quote\]#si";

$str1 =
'[quote]
  цитата
  [quote]  вложенная цитата[/quote]
  [quote]
    цитата вложенная в цитату
          [quote] 3 уровень вложености [/quote]
  [/quote]
[/quote]'
;
$str2 $str1;
$i 1;
while ( 
preg_match($parrent_old$str1) )
{
    
$str1 preg_replace($parrent_old"<div in=$i>\n$1\n</div end=$i>",  $str1);
    
$i++;
}
$i 1;
while ( 
preg_match($parrent_new$str2) )
{
    
$str2 preg_replace($parrent_new"<div in=$i>\n$1\n</div end=$i>",  $str2);
    
$i++;
}

echo 
"Вариант 1:\n"$str1;
echo 
"\n\n";
echo 
"Вариант 2:\n"$str2;

?>


Вариант 1:
<div in=1>

</div end=1>
  <div in=1>

</div end=1>
  [/quote]
[/quote]

Вариант 2:
<div in=3>
  цитата
  <div in=1>
  вложенная цитата
</div end=1>
  <div in=2>
    цитата вложенная в цитату
          <div in=1>
 3 уровень вложености 
</div end=1>
</div end=2>
</div end=3>


Пользуйтесь =)

   
 
 автор: MOVe   (15.11.2005 в 01:01)   письмо автору
 
   для: Artem S.   (15.11.2005 в 00:49)
 

Мдаааа... Круто :) Спасибо! Пока не асилил, но буду разбираться.
Куплю немножечко мозгофф... Приоритетно - с пониманием регекспов :)

   
 
 автор: MOVe   (15.11.2005 в 01:10)   письмо автору
 
   для: MOVe   (15.11.2005 в 01:01)
 

Боюсь показаться наглым, но всё же :)

Как вы поняли у меня задача сделать поддержку BBcodes на сайте. Есть какие-то более менее простые, но вот некоторые совсем не даются.

Очередной "затык" на списках...
Вот код:

[list]
  запись 1
  запись 2
  и т.д.
  [list]запись 3
    запись 4[/list]
[/list]


Как обработать так, чтобы это всё превратилось в:
<ul>
  <li>запись 1</li>
  <li>запись 2</li>
  <li>и т.д.</li>
    <ul>
      <li>запись 3</li>
      <li>запись 4</li>
    </ul>
</ul>


Сейчас ещё раз по форуму пройдусь, может уже есть такой ответ...
Заранее спасибо!

Да, при помощи обычного скрипта я это делаю детскими методами... А вот регекспами так же не понимаю...

   
 
 автор: Artem S.   (15.11.2005 в 01:17)   письмо автору
 
   для: MOVe   (15.11.2005 в 01:10)
 

Ну на сколько мне не изменяет память bbcode'ы нужно писать так
[list]
[*] запись 1
[*] запись 2
и т.д.
[list]
[*] запись 3
[*] запись 4[/list]
[/list]

Может лучше выбрать этот вариант?

   
 
 автор: MOVe   (15.11.2005 в 01:26)   письмо автору
 
   для: Artem S.   (15.11.2005 в 01:17)
 

Пользователю сложнее запомнить, что нужно ставить звёздочки... Лучше всё же без них. Если конечно код не усложнится... Лучше проверку по \n сделать, чем по [*]. Если не трудно :) Спасибо!

   
 
 автор: MOVe   (15.11.2005 в 11:46)   письмо автору
 
   для: MOVe   (15.11.2005 в 01:26)
 

Ещё одна задача... Как выбрать текст по границам тэгов? Но не трогать всё внутри?


[codee]
   bold 
  [codee]
    hello
  [/codee]
[/codee]

[codee]
  code tag 2
[/codee]


чтобы это превратилось в:

<div>
  [ b ] bold [ /b ]
  [codee]
    hello
  [/codee]
</div>

<div>
  code tag 2
</div>


В смысле, мне не нужно обработку внутренностей, мне нужно узнать, как мне вытащить тэги code только те, которые являются внешними...

   
 
 автор: cheops   (15.11.2005 в 13:45)   письмо автору
 
   для: MOVe   (15.11.2005 в 11:46)
 

Скорее всего разумнее разбить текст на части по границам тэгов - произвести замену внутри и объединить результаты.

   
 
 автор: MOVe   (17.11.2005 в 09:37)   письмо автору
 
   для: cheops   (15.11.2005 в 13:45)
 

А со списками мне никто не поможет :cry:?

   
 
 автор: Artem S.   (17.11.2005 в 10:19)   письмо автору
 
   для: MOVe   (17.11.2005 в 09:37)
 

>> Ещё одна задача... Как выбрать текст по границам тэгов? Но не трогать всё внутри?
Регами тут я ничего сделать не могу. Можно прибегнуть к рекрусии, но тогда между тегами ничего не доложно быть ([ b ][ i ][ code ]111[ /code ][ /i ][ /b ] так а не так [ b][ i ] 123 [ code ]111[ /code ][ /i ][ /b]

Спасти могут строковые функции. Ищем вложения [ b ] [ i ] [ code ] через strpos что раньше встречается min() и меняем по регвыражению что выше.

Со списками помогу, но чуть позже, я занят очень, на выходных.

   
 
 автор: MOVe   (17.11.2005 в 17:29)   письмо автору
 
   для: Artem S.   (17.11.2005 в 10:19)
 

Хорошо, спасибо. Если в принципе регами не сделать (по заключению экспертов) :), то напишу обычную функцию! Thx!

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования