Как связать URL-адреса в строке с помощью php?

У меня есть следующая строка:

"Look on http://www.google.com".

Мне нужно преобразовать его в:

"Посмотрите на http://www.google.com"

Исходная строка может содержать более одной строки URL.

Как мне это сделать в пхп?

Спасибо


person Alex    schedule 03.02.2009    source источник
comment
Вам нужно сделать отступ в 4 пробела, чтобы он не обрабатывал его. Я сделал это для тебя.   -  person Paolo Bergantino    schedule 03.02.2009
comment
Спасибо! Помогло, сейчас исправил.   -  person Alex    schedule 03.02.2009
comment


Ответы (10)


Вы можете использовать следующее:

$string = "Look on http://www.google.com";
$string = preg_replace(
              "~[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]~",
              "<a href=\"\\0\">\\0</a>", 
              $string);

Версии PHP ‹ 5.3 (ereg_replace), иначе (preg_replace)

person Ben    schedule 03.02.2009
comment
Спасибо, Бен, я тоже это нашел, но пока не успел проверить. - person Alex; 03.02.2009
comment
Не беспокойся! Я начал пытаться написать свое собственное регулярное выражение, чтобы сделать это, но потом понял, что это сложнее, чем я думал изначально, поэтому я был рад, что нашел что-то в Интернете! :-) - person Ben; 03.02.2009
comment
Для тех, кто может прочитать этот ответ: обратите внимание, что с PHP ›= 5.3 функции ereg_* устарели — и вместо этого вы должны использовать preg_*. - person Pascal MARTIN; 13.03.2011
comment
Это не сработало, если просто заменить ereg на pred (неизвестный модификатор '+'). Должен ли я изменить что-то еще? - person Nathan H; 02.12.2012
comment
@Ben есть новости о том, что сказал @nathanhazout? о Unknown modifier '+'. ошибка выскакивает если поменять с ereg_replace на preg_replace. Спасибо! - person Jo E.; 01.02.2014
comment
Чтобы исправить ошибку неизвестного модификатора «+», используйте это: $new_string = preg_replace("~[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]~","<a href=\"\\0\">\\0</a>", $string); - person Kiran Aghor; 17.02.2014

lib_autolink делает довольно хорошую работу, избегая подводных камней, таких как лишняя пунктуация после ссылки и ссылки внутри HTML-тегов:

https://github.com/iamcal/lib_autolink

person Cal    schedule 03.02.2009
comment
Я никогда не использовал его и даже почти не смотрел на него, но это кажется гораздо лучшим решением, чем попытка свернуть свой собственный. +1 - person rmeador; 03.02.2009
comment
Есть ли способ оставить http:// (протокол)? Я думаю, что это выглядит странно, когда http:// удаляется автоматически. - person Nathan; 26.06.2012
comment
@Nathan - да, в верхней части файла автоссылки lib есть поле autolink_options в массиве глобальных переменных. Установите значение 'strip_protocols' в false, и будут отображаться префиксы протокола. - person Andrey Butov; 26.12.2013

Взгляните на регулярные выражения. Затем вы должны сделать что-то например:

$text = preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $text);
person Bouke    schedule 03.02.2009
comment
Вам не хватает - в части пути должно быть @(https?://([-\w\.]+)+(:\d+)?(/([-\w/_\.]*(\?\S+)?)?)?)@ - person ianbarker; 13.09.2013

Небольшое обновление из наших дней. Просто регулярного выражения будет недостаточно. URL-адреса могут содержать символы Юникода, скобки, знаки препинания и т. д.

Существует библиотека подсветки URL, которая охватывает множество крайних случаев.

Пример:

<?php

use VStelmakh\UrlHighlight\UrlHighlight;

$urlHighlight = new UrlHighlight();
$urlHighlight->highlightUrls('Look on http://www.google.com or even google.com.');
// return: 'Look on <a href="http://www.google.com">http://www.google.com</a> or even <a href="http://google.com">google.com</a>.'
person vstelmakh    schedule 21.10.2020

Вам нужно будет использовать регулярные выражения...

Что-то вроде этого поможет.

$result = preg_replace('/\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[A-Z0-9+&@#\/%=~_|]/i', '<a href="\0">\0</a>', $text);
person Rik Heywood    schedule 03.02.2009

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

как-определить-urls-in-text-и-преобразовать-в-html-ссылки-php-используя-регулярные-выражения

<?php
// The Regular Expression filter
$pattern = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";

//example text
$text="Example user text with a URL http://www.zero7web.com , second link http://www.didsburydesign.co.uk";

// convert URLs into Links
$text= preg_replace($pattern, "<a href=\"\\0\" rel=\"nofollow\">\\0</a>", $text);

echo $text;
?>

Вероятно, хорошей идеей будет также добавить nofollow к ссылке, поскольку это значение, отправленное пользователем.

person Andrew    schedule 02.11.2009

Попробуй это...

<?

   function link_it($text)  
   {  
        $text= preg_replace("/(^|[\n ])([\w]*?)([\w]*?:\/\/[\w]+[^ \,\"\n\r\t<]*)/is", "$1$2<a href=\"$3\" >$3</a>", $text);  
        $text= preg_replace("/(^|[\n ])([\w]*?)((www)\.[^ \,\"\t\n\r<]*)/is", "$1$2<a href=\"http://$3\" >$3</a>", $text);
                $text= preg_replace("/(^|[\n ])([\w]*?)((ftp)\.[^ \,\"\t\n\r<]*)/is", "$1$2<a href=\"ftp://$3\" >$3</a>", $text);  
        $text= preg_replace("/(^|[\n ])([a-z0-9&\-_\.]+?)@([\w\-]+\.([\w\-\.]+)+)/i", "$1<a href=\"mailto:$2@$3\">$2@$3</a>", $text);  
        return($text);  
    }


$text = "ini link gue: http://sapua.com <br>
https://sapua.com <br>
anything1://www.sss.com <br>

dua www.google.com <br>
tiga http://www.google.com <br>

ftp.sapua.com <br>

[email protected]


";

print link_it($text);

?>
person Hannan Gigih Prastawa    schedule 16.07.2010

Я нашел этот код по адресу http://code.seebz.net/p/autolink-php/ и немного подправил его, чтобы он распознавал www.* как ссылки. Я не очень хорошо разбираюсь в регулярных выражениях, но я думаю, что две строки str_replace можно изменить на одно регулярное выражение.

<?php
$text = 'First link is: www.example.com. Second link is http://example.com. Third link is https://example.com. Fourth link is http://www.example.com. Fifth link is <a href="http://www.example.com">www.example.com</a>';

function autolink($str, $attributes=array()) {
$str = str_replace("http://www","www",$str);
$str = str_replace("https://www","www",$str);

$attrs = '';
foreach ($attributes as $attribute => $value) {
$attrs .= " {$attribute}=\"{$value}\"";
}
$str = ' ' . $str;
$str = preg_replace(
'`([^"=\'>])((http|https|ftp)://[^\s<]+[^\s<\.)])`i',
'$1<a href="$2"'.$attrs.'>$2</a>',
$str
);
$str = preg_replace(
'`([^"=\'>])((www).[^\s<]+[^\s<\.)])`i',
'$1<a href="http://$2"'.$attrs.'>$2</a>',
$str
);
$str = substr($str, 1);
return $str;
}

echo autolink($text);
?>
person Sam Lee    schedule 07.07.2015

Правильная ссылка на URL-адрес нетривиальна. (См.: http://www.codinghorror.com/blog/2008/10/the-problem-with-urls.html для получения дополнительной информации о том, почему это так.) Я потратил на это довольно много времени и нашел довольно хорошее решение проблемы ( для PHP и/или Javascript). См.: http://jmrware.com/articles/2010/linkifyurl/linkify.html

person ridgerunner    schedule 23.02.2011

Проверьте мою функцию linkify, которая использует preg_replace_callback (только для PHP 5.3). Он поддерживает http, электронную почту и твиттер:

http://www.jasny.net/articles/linkify-turning-urls-into-clickable-links-in-php/

/**
* Turn all URLs in clickable links.
*
* @param string $value
* @param array $protocols http/https, ftp, mail, twitter
* @param array $attributes
* @param string $mode normal or all
* @return string
*/
    function linkify($value, $protocols = array('http', 'mail'), array $attributes = array(), $mode = 'normal')
    {
        // Link attributes
        $attr = '';
        foreach ($attributes as $key => $val) {
            $attr = ' ' . $key . '="' . htmlentities($val) . '"';
        }

        $links = array();

        // Extract existing links and tags
        $value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);

        // Extract text links for each protocol
        foreach ((array)$protocols as $protocol) {
            switch ($protocol) {
                case 'http':
                case 'https': $value = preg_replace_callback($mode != 'all' ? '~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i' : '~([^\s<]+\.[^\s<]+)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { if ($match[1]) $protocol = $match[1]; $link = $match[2] ?: $match[3]; return '<' . array_push($links, '<a' . $attr . ' href="' . $protocol . '://' . $link . '">' . $link . '</a>') . '>'; }, $value); break;
                case 'mail': $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, '<a' . $attr . ' href="mailto:' . $match[1] . '">' . $match[1] . '</a>') . '>'; }, $value); break;
                case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#](\w++)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, '<a' . $attr . ' href="https://twitter.com/' . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1] . '">' . $match[0] . '</a>') . '>'; }, $value); break;
                default: $value = preg_replace_callback($mode != 'all' ? '~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i' : '~([^\s<]+)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, '<a' . $attr . ' href="' . $protocol . '://' . $match[1] . '">' . $match[1] . '</a>') . '>'; }, $value); break;
            }
        }

        // Insert all link
        return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
    }
person Arnold Daniels    schedule 08.03.2012
comment
Добро пожаловать в Stack Overflow! Хотя теоретически это может ответить на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки. - person Bill the Lizard; 08.03.2012
comment
@BilltheLizard Я не понимаю твоего замечания. Этот код делает именно то, о чем просит Алекс. Вам просто нужно скопировать/вставить. - person Arnold Daniels; 27.03.2012
comment
Кажется, работает здесь в моих тестах. Только одно предупреждение: если вы не используете его в классе (ООП), удалите public, иначе PHP выдаст фатальную ошибку синтаксического анализа. - person Artem Russakovskii; 14.01.2015