简体   繁体   中英

Regex to linkify URLs

I currently have the following regex to capture link text and a URL in the following format:

[Link](http://link.com)

\\[(.+)]\\(((https?:\\/\\/(?:www\\.|(?!www))[^\\s\\.]+\\.[^\\s]{2,}|www\\.[^\\s]+\\.[^\\s]{2,}))\\)

When I add another expression afterwards to linkify URLs, it messes up ones in the above format.

Is there a singular regular expression to handle both cases?

http://link.com -> <a href="http://link.com" target="_blank">http://link.com</a>

[Link](http://link.com) -> <a href="http://link.com" target="_blank">Link</a>

PHP:

$string = preg_replace('/\[(.+)]\(((https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,}))\)/', '<a href="$2" target="_blank">$1</a>', $string);

There's no real ways to identify an url in a string since the url syntax can be very complicated (too complicated to be clear). In other words, you must accept that something that looks like [...](...) stands for a link without to try to verify if the content between ( and ) is really an URL. (You can always use parse_url after, but keep in mind that it may exclude valid urls) .

What you are looking for is:

$result = preg_replace('~\[([^]]*)]\([^)]*\)~', '<a href="$2" target="_blank">$1</a>', $str);

// If you want to hunt lonely urls in your text, you can always search
// after extracting text nodes with XPath and a naive pattern like this:

$dom = new DOMDocument;
$dom->loadHTML($result);

$xp = new DOMXPath($dom);
$textNodes = $xp->query('//text()');

foreach($textNodes as $textNode) {
    $textNode->nodeValue = preg_replace('~[hw](?:(?<=\bh)ttps?://|(?<=\bw)ww\.)\S+~i', '<a href="$0" target="_blank">$0</a>~', $textNode->nodeValue);
}

$result = $dom->saveHTML();

Note: for better results, if you absolutely want to check the url, you can use the same pattern with preg_replace_callback , remove the last character of the match until parse_url works and perform the replacement, but it will not be very performant.

Maybe this help you a bit:

/**
 * Linkify Function
 * @param $tweet
 * @return mixed
 */
function linkify_tweet($tweet)
{
//Convert urls to <a> links
$tweet = preg_replace("/([\w]+\:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/", "<a href=\"mailto:w2m@bachecubano.com?subject=WEB $1\">$1</a>", $tweet);

//Convert hashtags to twitter searches in <a> links
$tweet = preg_replace("/#([A-Za-z0-9\/\.]*)/", "<a href=\"#\">#$1</a>", $tweet);

//Convert attags to twitter profiles in <a> links
$tweet = preg_replace("/@([A-Za-z0-9\/\.]*)/", "<a href=\"mailto:w2m@bachecubano.com?subject=MSG @$1\" class=\"userlink\">@$1</a>", $tweet);

return $tweet;
}

First deal with markdown syntax. Then catch plain links that were not processed - you may use similar regexp, but without parethesis. If you want to replace everything that looks like an url within whitespace limits (html won't match) then this will do:

\\s(https?:\\/\\/(?:www\\.|(?!www))[^\\s.]+\\.[^\\s]{2,}|www\\.[^\\s]+\\.[^\\s]{2,})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM