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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.