It is necessary to make a converter of inserted urls into clickable links, even without http: //. It turns out that horrible, because I'm not friends with the regulars, here's the code:

$text = 'Тестик test.ru http://test.ru'; $text = preg_replace('`(http(?:s)?://\w+[^\s\[\]\<]+)`i', '<a href="$1" target="_blank">$1</a>', $text); $text= preg_replace('/[a-zA-Z0-9]+\.(ru|com|net)/i', '<a href="$1" target="_blank">$1</a>', $text); echo $text; 
  • one
    " It turns out that horrible " - and it will, because there is no 100% reliable way to distinguish a link from a non-link, if it does not start from the protocol. Try first to narrow down the criteria and formulate clear rules for what to consider as a link and what is not. In words, not in regexp. - PinkTux
  • @PinkTux for what your listing domains? ru | com | net - Rammsteinik
  • I don’t know, because as a second regexp, you completely kill the results of the first one, and I don’t understand the logic of this action. - PinkTux
  • @ Rammsteinik, and target="_blank" better not to use anywhere at all. This is a vulnerability for your site;) - Visman
  • @ Visman, `target =" _ blank "` what’s the problem with that? - Rammsteinik

1 answer 1

 $text = 'Тестик 1.test.ru 2.<a href="http://www.test.ru">test.ru ok</a> 3.https://test.ru'; $patt = array( '%\b(?<!href=[\'"])https?://([^\s\[\]<]+)(?![^<>]*</a>)%i', '%\b(?<!http://)(?<!https://)[az\d]+\.(ru|com|net)(?!["\'][^<>]*>)(?![^<>]*</a>)%i' ); $repl = array( '<a href="$0">$1</a>', '<a href="http://$0">$0</a>' ); $text = preg_replace($patt, $repl, $text); echo $text; 

Here:

\b - word boundary, it is needed here to capture the entire word (for example, test ), and not part of it ( est );

(?<!href=[\'"]) - excludes link capture from tag A (for example, from here <a href="http://test.ru"> );

(?<!http://)(?<!https://) - excludes the capture of links from those processed by the first regular schedule;

(?![^<>]*</a>) - excludes link capture from tag A (for example, from here test.ru ok</a> );

(?!["\'][^<>]*>) - excludes link capturing from the A tag (for example, from here <a href="http://www.test.ru"> ).

PS This decision still does not take into account all the nuances;)

UPD Option with more complex regulars, close to RFC 1738

 $text = 'Тестик 1. abc.test.ru 2. <a href="http://www.test.ru">http://test.ru ok</a> 3. https://test.ru/search?search_id=975080714'; $patt = array( '%\b(?<!href=[\'"])(?>https?://|www\.)([\p{L}\p{N}]+[\p{L}\p{N}\-]*\.(?:[\p{L}\p{N}\-]+\.)*[\p{L}\p{N}]{2,})(?::\d+)?(?:(?:(?:/[\p{L}\p{N}$_\.\+!\*\'\(\),\%;:@&=-]+)+|/)(?:\?[\p{L}\p{N}$_\.\+!\*\'\(\),\%;:@&=-]+)?(?:#[^\s\<\>]+)?)?(?![^<]*+</a>)%u', '%\b(?<!http://)(?<!https://)([\p{L}\p{N}]+[\p{L}\p{N}\-]*\.(?:[\p{L}\p{N}\-]+\.)*(?:ru|com|net))(?::\d+)?(?:(?:(?:/[\p{L}\p{N}$_\.\+!\*\'\(\),\%;:@&=-]+)+|/)(?:\?[\p{L}\p{N}$_\.\+!\*\'\(\),\%;:@&=-]+)?(?:#[^\s\<\>]+)?|\b)(?![^<]*+</a>)%u' ); $repl = array( '<a href="$0">$1</a>', '<a href="http://$0">$1</a>' ); $text = preg_replace($patt, $repl, $text); echo $text; 
  • Thank you, do not tell zxc.test.ru how to solve the problem with subdomains, zxc.test.ru sees as zxc.<a href="http://test.ru">test.ru</a> - Rammsteinik
  • @ Rammsteinik, [az\d]+ in the second regular season, you can try to replace it with (?:[az\d]+(?:[az\d\.]*[az\d])?) . - Visman