регулярное выражение, чтобы превратить URL-адреса в ссылки, не связываясь с существующими ссылками в тексте - PullRequest
3 голосов
/ 11 июня 2009

Я пытаюсь преобразовать URL-адреса фрагмента текста в гиперссылки, используя регулярные выражения. Мне удалось этого добиться, но проблема в том, что в тексте уже есть ссылки

так

bla bla blah www.google.com bla blah <a href="www.google.com">www.google.com</a>

должно привести к

bla bla blah <a href="http://www.google.com">www.google.com</a> bla blah <a href="www.google.com">www.google.com</a> 

не

bla bla blah <a href="http://www.google.com">www.google.com</a> bla blah <a href="<a href="http://www.google.com">www.google.com</a></a>"><a href="http://www.google.com">www.google.com</a></a>

Ответы [ 4 ]

3 голосов
/ 24 сентября 2009

Наконец закончил это:

function add_url_links($data)
{
        $data = preg_replace_callback('/(<a href=.+?<\/a>)/','guard_url',$data);

        $data = preg_replace_callback('/(http:\/\/.+?)([ \\n\\r])/','link_url',$data);
        $data = preg_replace_callback('/^(http:\/\/.+?)/','link_url',$data);
        $data = preg_replace_callback('/(http:\/\/.+?)$/','link_url',$data);

        $data = preg_replace_callback('/{{([a-zA-Z0-9+=]+?)}}/','unguard_url',$data);

        return $data;
}

function guard_url($arr) { return '{{'.base64_encode($arr[1]).'}}'; }
function unguard_url($arr) { return base64_decode($arr[1]); }
function link_url($arr) { return guard_url(array('','<a href="'.$arr[1].'">'.$arr[1].'</a>')).$arr[2]; }
3 голосов
/ 11 июня 2009

Это почти невозможно сделать с помощью одного регулярного выражения. Вместо этого я бы рекомендовал подход, основанный на конечных автоматах. Примерно так (в псевдокоде)

state = OUTSIDE_LINK
for pos (0 .. length input)
   switch state
   case OUTSIDE_LINK
     if substring at pos matches /<a/
       state = INSIDE_LINK
     else if substring at pos matches /(www.\S+|\S+.com|\S+.org)/
       substitute link
   case INSIDE_LINK
     if substring at post matches /<\/a>/
       state = OUTSIDE_LINK
2 голосов
/ 12 июня 2009

Другой способ сделать это (в php)

    $strParts = preg_split( '/(<[^>]+>)/', $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
    foreach( $strParts as $key=>$part ) {

        /*check this part isn't a tag or inside a link*/
        if( !(preg_match( '@(<[^>]+>)@', $part ) || preg_match( '@(<a[^>]+>)@', $strParts[$key - 1] )) ) {
            $strParts[$key] = preg_replace( '@((http(s)?://)?(\S+\.{1}[^\s\,\.\!]+))@', '<a href="http$3://$4">$1</a>', $strParts[$key] );
        }

    }
    $html = implode( $strParts );
1 голос
/ 22 сентября 2009

Еще один прием - защитить все существующие ссылки, кодируя код, затем заменяя URL-адреса ссылками, а затем расшифровывая защищенные ссылки.

$data = 'test http://foo <a href="http://link">LINK</a> test';

$data = preg_replace_callback('/(<a href=".+?<\/a>)/','guard_url',$data);

$data = preg_replace_callback('/(http:\/\/.+?)([ .\\n\\r])/','link_url',$data);

$data = preg_replace_callback('/{{([a-zA-Z0-9+]+?)}}/','unguard_url',$data);

print $data;

function guard_url($arr) { return '{{'.base64_encode($arr[1]).'}}'; }
function unguard_url($arr) { return base64_decode($arr[1]); }
function link_url($arr) { return '<a href="'.$arr[1].'">'.$arr[1].'</a>'.$arr[2]; }

Приведенный выше код является просто доказательством концепции и не обрабатывает все ситуации. Тем не менее, вы можете видеть, что код довольно прост.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...