Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Тексты > BBcode разбор


Автор: kvv 4.5.2006, 14:45
Код

$txt='<b><i>так</b></i>';
$patterns=array('/\[b\](.*?)\[\/b\]/si','/\[u\](.*?)\[\/u\]/si','/\[i\](.*?)\[\/i\]/si');
$replacements=array('<b>\\1</b>','<u>\\1</u>','<i>\\1</i>');
$txt = preg_replace($patterns,$replacements,$txt);


Текст отпарсится так: <b><i>так</b></i>. Для обычного браузера еще ничего, но в во флеше это криво воспримется - последующий текст будет жирным. Как это можно исправить? 

Автор: IvanB 4.5.2006, 16:12
У тебя что написано? smile
Ты 
Код
'/\[b\](.*?)\[\/b\]/si'
 заменяешь на 
Код
'<b>\\1</b>'
......
У тебя в строке такого нет. smile 
$txt которая.  

Автор: kvv 4.5.2006, 17:48
Описка.
Код
$txt='[b][i]так[/b][/i]';
$patterns=array('/\[b\](.*?)\[\/b\]/si','/\[u\](.*?)\[\/u\]/si','/\[i\](.*?)\[\/i\]/si');
$replacements=array('<b>\\1</b>','<u>\\1</u>','<i>\\1</i>');
$txt = preg_replace($patterns,$replacements,$txt);

 

Автор: Mal Hack 4.5.2006, 18:45
Я вообще по другому делал...
Глянул, делал вообще не оптимально...
Я бы тут сейчас сделал бы так:
Код

$txt = preg_replace("#]\(b|i|u)\](.+?)\[/\\1\]#ie","<\\1>\\2</\\1>",$txt);
 

Автор: S.A.P. 5.5.2006, 14:00
Mal Hack, а как быть со вложенными тегами? 

Автор: Replicator 5.5.2006, 14:33
Прогнать регулярку несколько раз. Я у себя дважды это делаю, хотя можно это делать в цикле, пока все не заменишь.

P.S. MalHack, спасибо за код. А то у меня гораздо длиннее выражение, да и помедленней. 

Автор: S.A.P. 5.5.2006, 15:39
Цитата(Replicator @  5.5.2006,  14:33 Найти цитируемый пост)
Я у себя дважды это делаю, хотя можно это делать в цикле, пока все не заменишь.
 почему дважды? почему не 3 ... не 5.

И как оптиматьно определить, что еще не все заменилось? 

 smile  

Автор: R.M. 5.5.2006, 15:48
S.A.P., можно проверить соответствие строк если заменённая равна той которая была до этого прекращать цикл smile  

Автор: Mal Hack 5.5.2006, 18:59
Цитата(S.A.P. @  5.5.2006,  14:00 Найти цитируемый пост)
Mal Hack, а как быть со вложенными тегами?  


Цитата(Replicator @  5.5.2006,  14:33 Найти цитируемый пост)
Прогнать регулярку несколько раз. Я у себя дважды это делаю, хотя можно это делать в цикле, пока все не заменишь.


Цитата(Куксикус @  5.5.2006,  15:48 Найти цитируемый пост)
S.A.P., можно проверить соответствие строк если заменённая равна той которая была до этого прекращать цикл smile   


А для чего я там модификатор e поставил?
Ну тут вообще тогда надо бы делать через preg_replace_callback, в принципе это лучше с той стороны, что в плане кодинга интеитивнее понятнее и есть больше шансов на дальнейшее улучшение. 

Автор: kvv 5.5.2006, 22:23
Код
<?php
$txt=' [b] [i] test [/b] [/i]   [b] [i] test [/i] [/b]';
$txt = preg_replace("#]\(b|i|u)\](.+?)\[/\\1\]#ie","<\\1>\\2</\\1>",$txt);
echo htmlspecialchars($txt);
?>

Warning: Compilation failed: reference to non-existent subpattern at offset 8 in c:\program files\apache group\apache\htdocs\test.php on line 5 

Автор: Mal Hack 5.5.2006, 23:53
Код
<?php
$txt=' [b] [i] test [/b] [/i]   [b] [i] test [/i] [/b]';
$txt = preg_replace("#\[(b|i|u)+\](.+?)\[/\\1\]#ies","<\\1>\\2</\\1>",$txt);
echo htmlspecialchars($txt);
?>


Отладь сам. 

Автор: kvv 6.5.2006, 06:38
Не очень силен в регах. Поясните пожалуста:
Цитата
e
If this modifier is set, preg_replace() does normal substitution of backreferences in the replacement string, evaluates it as PHP code, and uses the result for replacing the search string. 

Если этот модификатор установлен, функция делает нормальную замену обратных ссылок в скроке замены, выполняет это как пхп код, и использует результ для замены в поисковой строке.
Как это понять?

Еще не пойму смысла знака # в начала и в конце. В хелпе написано только это:
Цитата
If the PCRE_EXTENDED option is set, an unescaped # character outside a character class introduces a comment that continues up to the next newline character in the pattern. 

Но у нас PCRE_EXTENDED  не установлен. Да и зачем закомменчивать всю строку?


Вот, что у меня получилось(убрал #, заэкранил \):
Код
<?php
$txt=' [b] [i] test [/b] [/i]   [b] [i] test [/i] [/b]';
$txt = preg_replace("/\[(b|i|u)\](.+?)\[\/\\1\]/is","<\\1>\\2</\\1>",$txt);
echo htmlspecialchars($txt);
?>

Выдает:
Код
<b> [i] test </b> [/i] <b> [i] test [/i] </b>

Но замена-то  сделана по-одному разу, а если использовать квантификатор e, то выдает это:
Код
Parse error: parse error in c:\program files\apache group\apache\htdocs\test.php(3) : regexp code on line 1

Fatal error: Failed evaluating code: [i] test in c:\program files\apache group\apache\htdocs\test.php on line 3
  

Автор: S.A.P. 6.5.2006, 08:37
Цитата(Куксикус @  5.5.2006,  15:48 Найти цитируемый пост)
S.A.P., можно проверить соответствие строк если заменённая равна той которая была до этого прекращать цикл 

это далеко не оптимальное решение  smile .


kvv, может быть Mal Hack, имел ввиду вот это:
Код

$txt=' [b] [i] test [/b] [/i]   [b] [i] test [/i] [/b]';
function BBCode($str)
{
    return preg_replace("#\[(b|i|u)+\](.+?)\[/\\1\]#ies","'<$1>'.BBCode('$2').'</$1>'",$str);
}

echo htmlspecialchars(BBCode($txt));


но у меня есть подозрения, что код будет медленно работать... 

Автор: kvv 7.5.2006, 05:55
Ну хотя-бы работает. Всем спасибо. 

Автор: Mal Hack 7.5.2006, 10:34
Цитата(S.A.P. @  6.5.2006,  08:37 Найти цитируемый пост)
kvv, может быть Mal Hack, имел ввиду вот это:

Вообще-то я несколько другое имел ввиду...
Реги сами поддерживают рекурсивный проход, но вот синтаксис точно не помню.
К примеру при таком варианте не прокатит вот это:
Не должно по крайней мере.
Код
$txt=' [b] [i] test [/b] [/i]   [b] [i] test [/i] [/b]';
 

Автор: S.A.P. 7.5.2006, 16:10
Цитата(kvv @  7.5.2006,  05:55 Найти цитируемый пост)
Ну хотя-бы работает. Всем спасибо.  
 это я привел для примера. Для рабочего решения это явно не катит, т.к. существует проблема с кавычками. С рекурсивными регами у меня ничего не вышло (может при замене они не работают?). 

Если собираешься использовать ручную рекурсию, то советую разобраться и переделать код на preg_replace_callback.
  

Автор: kvv 7.5.2006, 16:46
Не пойму вас.
Мне тот вариант понравился. Вроде все работает.
Смысла в preg_replace_callback() не увидел, ведь это тоже самое получается...  Может, я что-то там не понимаю?

Код
<?php
function BBCode($str)
{
    return preg_replace("#\[(b|i|u)+\](.+?)\[/\\1\]#ies","'<$1>'.BBCode('$2').'</$1>'",$str);
}

$txt='
[b] [i] ttt [/i] [/b]
[b] [i] ttt [/b] [/i]
[b] [i] [u] ttt [/u] [/i] [/b]
[b] [i] [u] ttt [/u] [/b] [/i]
[b] [i] [u] ttt [/u] [/u] [/u]
[b] [i] [u] ttt [/b] [/u] [/i]';
echo nl2br(htmlspecialchars(BBCode($txt)));
?>

Код
<b> <i> ttt </i> </b>
<b> [i] ttt </b> [/i]
<b> <i> <u> ttt </u> </i> </b>
<b> [i] <u> ttt </u> </b> [/i]
<b> [i] <u> ttt </u> [/u] [/u]
[b] [i] [U] ttt </b> [/U] [/i]
  

Автор: Mal Hack 7.5.2006, 23:23
Хм... Что-то через рекурсию внутри шаблонов у меня не получилось. Сделал вот так:
Код
<?php
function BBCode($str,$str2="",$str3="")
{
    if( isset($str2) && isset($str3) )
    {
    $str = "<".$str.">".$str2."</".$str.">".$str3;
        
        
    }
    return preg_replace("#\[(b|i|u)+\](.+?)\[/\\1\](.*?)$#ies","BBCode('$1','$2','$3')",$str);
}
$txt='
[b] [i] ttt [/i] [/b]
[b] [i] ttt [/b] [/i]
[b] [i] [u] ttt [/u] [/i] [/b]
[b] [i] [u] ttt [/u] [/b] [/i]
[b] [i] [u] ttt [/u] [/u] [/u]
[b] [i] [u] ttt [/b] [/u] [/i]';
echo nl2br(htmlspecialchars(BBCode($txt)));
?>
 

Автор: kvv 8.5.2006, 05:28
Эм... непонял. Мы берем тег в квадратных скобках, в BBCode() он оказывается в переменной $str - и потом в нем мы опять ищем рег?

Код
<?php
function BBCode($str,$str2="",$str3="")
{
    if( isset($str2) && isset($str3) )
    {
    $str = "<".$str.">".$str2."</".$str.">".$str3;
        
        
    }
    return preg_replace("#\[(b|i|u)+\](.+?)\[/\\1\](.*?)$#ies","BBCode('$1','$2','$3')",$str);
}
$txt=Array(
'[b] [i] ttt [/i] [/b]',
'[b] [i] ttt [/b] [/i]',
'[b] [i] [u] ttt [/u] [/i] [/b]',
'[b] [i] [u] ttt [/u] [/b] [/i]',
'[b] [i] [u] ttt [/u] [/u] [/u]',
'[b] [i] [u] ttt [/b] [/u] [/i]'
);
foreach($txt as $key => $value)
{
    echo htmlspecialchars(BBCode($value)).'<br>';
}
?>

Выдает:
Код
<<b> <i> ttt </i> </b>></<b> <i> ttt </i> </b>>
<<b> <i> ttt </b> </i>></<b> <i> ttt </b> </i>>
<<b> <i> <u> ttt </u> </i> </b>></<b> <i> <u> ttt </u> </i> </b>>
<<b> <i> <u> ttt </u> </b> </i>></<b> <i> <u> ttt </u> </b> </i>>
<[b] [i] <u> ttt </u> [/u] [/u]></[b] [i] <u> ttt </u> [/u] [/u]>
<<b> <i> <u> ttt </b> </u> </i>></<b> <i> <u> ttt </b> </u> </i>>

Ну так и есть... Получились теги в тегах%) 

Автор: Mal Hack 8.5.2006, 12:44
Цитата(kvv @  8.5.2006,  05:28 Найти цитируемый пост)
Ну так и есть... Получились теги в тегах%)

А как надо?

Цитата(kvv @  8.5.2006,  05:28 Найти цитируемый пост)
Мы берем тег в квадратных скобках, в BBCode() он оказывается в переменной $str - и потом в нем мы опять ищем рег?

Другого выхода я пока не вижу, т.к. рекурсивные шаблоны у меня не стали работать. 

Автор: kvv 8.5.2006, 14:00
Цитата(Mal Hack @  8.5.2006,  13:44 Найти цитируемый пост)
А как надо?

Мой второй пост сверху - там как раз получилось как надо. Ведь самое главное - чтоб не было перекрывания тегов, то есть ситуаций типа <b><i>smth</b></i> 

Автор: Mal Hack 8.5.2006, 14:31
Код
<?php
function BBCode($str,$str2="",$str3="")
{
    if( isset($str2) && isset($str3) )
    {
    $str = "<".$str.">".$str2."</".$str.">";
        
        
    }
    return preg_replace("#\[(b|i|u)+\](.+?)\[/\\1\]#ies","BBCode('$1','$2')",$str);
}
$txt='
[b] [i] ttt [/i] [/b]
[b] [i] ttt [/b] [/i]
[b] [i] [u] ttt [/u] [/i] [/b]
[b] [i] [u] ttt [/u] [/b] [/i]
[b] [i] [u] ttt [/u] [/u] [/u]
[b] [i] [u] ttt [/b] [/u] [/i]';
echo nl2br(htmlspecialchars(BBCode($txt)));
?>
 

Автор: kvv 8.5.2006, 14:40
Mal Hack, 
Мы друг друга не понимаем%) Уже ж все получилось - чего еще париться то?
Предлагаешь ты все ту же рекурсию - скорость парсинга не увеличивается.
Да и что-то ты не то в последнем коде делаешь... Третья переменная в функцию не передается, а ты ее иссетом проверяешь... И выводит он совем не то. 

Автор: Mal Hack 8.5.2006, 14:57
Тогда не понимаю в чем проблема?
Вот подправленный:
Код

<?php
function BBCode($str)
{

    return preg_replace("#\[(b|i|u)+\](.+?)\[/\\1\]#ies","'<$1>'.BBCode('$2').'</\\1>'",$str);
}
$txt='
[b] [i] ttt [/i] [/b]
[b] [i] ttt [/b] [/i]
[b] [i] [u] ttt [/u] [/i] [/b]
[b] [i] [u] ttt [/u] [/b] [/i]
[b] [i] [u] ttt [/u] [/u] [/u]
[b] [i] [u] ttt [/b] [/u] [/i]';
echo nl2br(htmlspecialchars(BBCode($txt)));
?>
 

Автор: BobiKK 11.5.2006, 18:30
Кстати, а это никто не пробовал? http://pear.php.net/package/HTML_BBCodeParser 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)