PHP — парсер BBCode — анализирует как тег ссылки bbcode, так и ссылку без тега

Мне нужно сделать это:

когда пользователь вставляет тег BBCode, с preg_replace и regex я делаю некоторую трансформацию.

e.g.

function forumBBCode($str){
   $format_search=array(
      '#\[url=(.*?)\](.*?)\[/url\]#i'
   );

   $format_replace=array(
      '<a class="lforum" target="_blank" href="$1">$2</a>'
   );

   $str=preg_replace($format_search, $format_replace, $str);
   $str=nl2br($str);
   return $str;
}

теперь я хочу также это: когда пользователь вставляет обычный текст со ссылкой, это тоже должно быть преобразовано. я не могу сделать это через функцию preg_replace, потому что если я напишу код как

$format_search
'#(www\..*?)#i'

$format_replace
'<a class="lforum" target="_blank" href="$1">$1</a>'

он преобразует ссылку 2 раза (в [url] и когда ссылка без этого тега).

поэтому я думаю об этой функции:

    function checkLinks($string) {
    $arrelab="";
    $arr=split(' |\r\n', $string);
    for($i=0; $i<sizeof($arr); $i++) {
        echo $i." - ".$arr[$i]."<br/>";
        if ((strpos($arr[$i], 'www.')!==false) or (strpos($arr[$i], 'http://')!==false) or (strpos($arr[$i], 'ftp://')!==false)) {
            if (strpos($arr[$i], '[url=')===false) {
                $arr[$i]='<a class="lforum" target="_blank" href="'.$arr[$i].'">'.$arr[$i].'</a>';
            }
        }

        $arrelab=$arrelab." ".$arr[$i];
    }
    return $arrelab;
}

проблема в том, что мне нужно разделить как для новой строки, так и для пустого места. любая помощь будет оценена.

p.s. Извините за мой плохой английский :)

ваше здоровье


person markzzz    schedule 09.07.2010    source источник


Ответы (4)


Это легко обойти с помощью проверки назад.

preg_replace('#(?<![>/"])((http://)?www.........)#im', '<a href="$1">$1</a>'

Таким образом, регулярное выражение будет пропускать любой URL-адрес, заключенный в " или › или предшествующий /
Это обходной путь, а не решение.

PS: target="_blank" приставал к пользователю. Вырежьте это.

person mario    schedule 09.07.2010
comment
хм, я не понимаю, что именно вы имеете в виду под этим кодом. если у меня есть текст, не заключенный в или › выражение не оценивается? должно быть хорошим регулярное выражение, которое не оценивает текст http://, если у него есть строка [url=, но я не могу этого сделать... - person markzzz; 09.07.2010
comment
Что делает это регулярное выражение, так это гарантирует, что URL-адрес уже не заключен в ссылку. Запустите его после регулярного выражения [url=. - person Aaron Harun; 09.07.2010
comment
ах ладно, теперь я понимаю, что он имеет в виду :) хороший, кажется, хороший :) ps1. если я хочу, чтобы все символы были разрешены после www, это должно быть хорошо, нет? www\..?* но похоже виноват... ps2. если я хочу и http и ftp? я пишу (?:http|ftp) вместо (http://)? - person markzzz; 10.07.2010
comment
Нет, я отредактировал свой ответ с помощью регулярного выражения, которое вы бы использовали. (Примите Марио, если вы его используете.) - person Aaron Harun; 10.07.2010
comment
Tnx Марио и Аарон :) хорошая съемка! p.s. почему это не решение? просто ради любопытства... - person markzzz; 10.07.2010
comment
Потому что он работает вокруг проблемы, а не решает ее напрямую. Решение этой проблемы будет означать, что в первую очередь нет столкновения. - person Aaron Harun; 10.07.2010
comment
да, но для моей проблемы достаточно :) NBBC был бы решением, но я предпочитаю не использовать внешние библиотеки :) - person markzzz; 11.07.2010

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

Обновление от Мариоса:

preg_replace('#(?<![>/"])(((http|https|ftp)://)?www[a-zA-Z0-9\-_\.]+)#im', '<a href="$1">$1</a>'

person Aaron Harun    schedule 09.07.2010
comment
Там я исправил не жадный вариант. - person Aaron Harun; 10.07.2010
comment
да, это рулит! если честно, я не понимаю, почему это работает, но я изучу это как упражнение для регулярного выражения! спасибо еще раз вам и марио :) - person markzzz; 10.07.2010

О вашей проблеме можно узнать, прочитав заголовок. Синтаксический анализ в сочетании с регулярным выражением

Вы не можете «анализировать» html или bb-код с помощью регулярного выражения, потому что они не являются обычными языками.

Вы должны написать (или найти) парсер bb-кода вместо использования регулярных выражений.

Первый результат Google для анализатора BB-кода: NBBC: новый анализатор BBCode. Но я им не пользовался, поэтому о качестве ничего сказать не могу.

person Jacco    schedule 09.07.2010

Есть более простой способ сделать это. Я создал обзор в блоге разработчиков RedBonzai. Ссылка на него здесь: http://www.redbonzai.com/blog/web-development/how-to-create-a-bb-codes-function-in-php/

Дайте знать, если у вас появятся вопросы.

КрасныйБонзай

person RedBonzai Developers    schedule 14.10.2010