49

I have this text:

$string = "this is my friend's website http://example.com I think it is coll"; 

How can I extract the link into another variable?

I know it should be by using regular expression especially preg_match() but I don't know how?

2
  • 1
    possible duplicate of Extract URL from string Commented Jul 18, 2013 at 1:18
  • 4
    @ Michael Berkowski how it will be duplicate the user asked on May 26 '09 at 14:13 but link mentioned by you asked on Dec 8 '10 at 17:44. May be the reverse may true. Commented Mar 18, 2015 at 10:44

14 Answers 14

51

Probably the safest way is using code snippets from WordPress. Download the latest one (currently 3.1.1) and see wp-includes/formatting.php. There's a function named make_clickable which has plain text for param and returns formatted string. You can grab codes for extracting URLs. It's pretty complex though.

This one line regex might be helpful.

preg_match_all('#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#', $string, $match); 

But this regex still can't remove some malformed URLs (ex. http://google:ha.ckers.org ).

See also: How to mimic StackOverflow Auto-Link Behavior

Sign up to request clarification or add additional context in comments.

6 Comments

I had a play around with the Wordpress formatting.php and using make_clickable is a nice idea but it ends up sucking in half of wordpress in dependencies.
Good one, to make sure the terminal part is not a weird character
This doesn't identify url without http, like google.com
This regex will match google:ha.ckers.org "@https?:\/\/(www\.)?[-a-zA-Z0-9\@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()\@:%_\+.~#?&//=]*)@"; Dont remeber where i found it so can't give credit
stackoverflow.com/questions/23366790/… worked better for me than this (context WordPress).
|
18

I tried to do as Nobu said, using Wordpress, but to much dependencies to other WordPress functions I instead opted to use Nobu's regular expression for preg_match_all() and turned it into a function, using preg_replace_callback(); a function which now replaces all links in a text with clickable links. It uses anonymous functions so you'll need PHP 5.3 or you may rewrite the code to use an ordinary function instead.

<?php /** * Make clickable links from URLs in text. */ function make_clickable($text) { $regex = '#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#'; return preg_replace_callback($regex, function ($matches) { return "<a href=\'{$matches[0]}\'>{$matches[0]}</a>"; }, $text); } 

1 Comment

Just a note: I've updated your answer to use a anonymous function as a callback instead of using create_function().
14

URLs have a quite complex definition — you must decide what you want to capture first. A simple example capturing anything starting with http:// and https:// could be:

preg_match_all('!https?://\S+!', $string, $matches); $all_urls = $matches[0]; 

Note that this is very basic and could capture invalid URLs. I would recommend catching up on POSIX and PHP regular expressions for more complex things.

Comments

11

The code that worked for me (especially if you have several links in your $string):

$string = "this is my friend's website https://www.example.com I think it is cool, but this one is cooler https://www.stackoverflow.com :)"; $regex = '/\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i'; preg_match_all($regex, $string, $matches); $urls = $matches[0]; // go over all links foreach($urls as $url) { echo $url.'<br />'; } 

Hope that helps others as well.

1 Comment

i've tested all answer, this is only one will remove the html tab
8

If the text you extract the URLs from is user-submitted and you're going to display the result as links anywhere, you have to be very, VERY careful to avoid XSS vulnerabilities, most prominently "javascript:" protocol URLs, but also malformed URLs that might trick your regexp and/or the displaying browser into executing them as Javascript URLs. At the very least, you should accept only URLs that start with "http", "https" or "ftp".

There's also a blog entry by Jeff where he describes some other problems with extracting URLs.

Comments

5
preg_match_all('/[a-z]+:\/\/\S+/', $string, $matches); 

This is an easy way that'd work for a lot of cases, not all. All the matches are put in $matches. Note that this do not cover links in anchor elements (<a href=""...), but that wasn't in your example either.

3 Comments

-1: you've just created an XSS vulnerability, since it would also extract javascript: URLs.
It's not stated what he'd use it for, hence I don't account for that. He just wanted to get URLs into variables.
@Michael: Finding javascript URLs is not yet a vulnerability; using them without any check is. Sometimes the presence and number of such URLs is useful information. I'd have chosen a different delimiter. :)
3

You could do like this..

<?php $string = "this is my friend's website http://example.com I think it is coll"; echo explode(' ',strstr($string,'http://'))[0]; //"prints" http://example.com 

Comments

2

You could try this to find the link and revise the link (add the href link).

$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/"; // The Text you want to filter for urls $text = "The text you want to filter goes here. http://example.com"; if(preg_match($reg_exUrl, $text, $url)) { echo preg_replace($reg_exUrl, "<a href="{$url[0]}">{$url[0]}</a> ", $text); } else { echo "No url in the text"; } 

refer here: http://php.net/manual/en/function.preg-match.php

Comments

1
preg_match_all ("/a[\s]+[^>]*?href[\s]?=[\s\"\']+". "(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/", $var, &$matches); $matches = $matches[1]; $list = array(); foreach($matches as $var) { print($var."<br>"); } 

Comments

1

There are a lot of edge cases with urls. Like url could contain brackets or not contain protocol etc. Thats why regex is not enough.

I created a PHP library that could deal with lots of edge cases: Url highlight.

Example:

<?php use VStelmakh\UrlHighlight\UrlHighlight; $urlHighlight = new UrlHighlight(); $urlHighlight->getUrls("this is my friend's website http://example.com I think it is coll"); // return: ['http://example.com'] 

For more details see readme. For covered url cases see test.

Comments

1

Here is a function I use, can't remember where it came from but seems to do a pretty good job of finding links in the text. and making them links.

You can change the function to suit your needs. I just wanted to share this as I was looking around and remembered I had this in one of my helper libraries.

function make_links($str){ $pattern = '(?xi)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))'; return preg_replace_callback("#$pattern#i", function($matches) { $input = $matches[0]; $url = preg_match('!^https?://!i', $input) ? $input : "http://$input"; return '<a href="' . $url . '" rel="nofollow" target="_blank">' . "$input</a>"; }, $str); } 

Use:

$subject = 'this is a link http://google:ha.ckers.org maybe don't want to visit it?'; echo make_links($subject); 

Output

this is a link <a href="http://google:ha.ckers.org" rel="nofollow" target="_blank">http://google:ha.ckers.org</a> maybe don't want to visit it? 

Comments

1
<?php preg_match_all('/(href|src)[\s]?=[\s\"\']?+(.*?)[\s\"\']+.*?/', $webpage_content, $link_extracted); 

preview

Comments

0

This Regex works great for me and i have checked with all types of URL,

<?php $string = "Thisregexfindurlhttp://www.rubular.com/r/bFHobduQ3n mixedwithstring"; preg_match_all('/(https?|ssh|ftp):\/\/[^\s"]+/', $string, $url); $all_url = $url[0]; // Returns Array Of all Found URL's $one_url = $url[0][0]; // Gives the First URL in Array of URL's ?> 

Checked with lots of URL's can find here http://www.rubular.com/r/bFHobduQ3n

Comments

0
public function find_links($post_content){ $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/"; // Check if there is a url in the text if(preg_match_all($reg_exUrl, $post_content, $urls)) { // make the urls hyper links, foreach($urls[0] as $url){ $post_content = str_replace($url, '<a href="'.$url.'" rel="nofollow"> LINK </a>', $post_content); } //var_dump($post_content);die(); //uncomment to see result //return text with hyper links return $post_content; } else { // if no urls in the text just return the text return $post_content; } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.