如何用链接替换普通URL?

javascript regex

224709 观看

22回复

31477 作者的声誉

我使用下面的函数来匹配给定文本中的URL并替换它们用于HTML链接。正则表达式工作得很好,但目前我只是替换了第一场比赛。

我如何替换所有的URL?我想我应该使用exec命令,但我并没有真正想到如何做到这一点。

function replaceURLWithHTMLLinks(text) {
    var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/i;
    return text.replace(exp,"<a href='$1'>$1</a>"); 
}
作者: Sergio del Amo 的来源 发布者: 2008 年 9 月 1 日

回应 22


284

11128 作者的声誉

用链接替换URL(回答一般问题)

问题中的正则表达式错过了很多边缘情况。在检测URL时,最好使用专门的库来处理国际域名,新的顶级域名(如TLD).museum,括号和URL末尾的其他标点符号以及许多其他边缘情况。有关其他一些问题的解释,请参阅Jeff Atwood的博客文章The URL with URL

URL匹配库最佳摘要Dan Dascalescu的答案中+100
(截至2014年2月)


“使正则表达式替换多个匹配”(具体问题的答案)

在正则表达式的末尾添加“g”以启用全局匹配:

/ig;

但这只能解决正则表达式只替换第一个匹配的问题。不要使用该代码。

作者: Sam Hasler 发布者: 2008 年 9 月 1 日

0

0 作者的声誉

我必须做相反的事情,并将html链接改为URL,但我修改了你的正则表达式,它就像一个魅力,谢谢:)

var exp = / * <\ / A> / IG;

source = source.replace(exp,“$ 1”);
作者: Reece 发布者: 2009 年 4 月 27 日

23

437 作者的声誉

谢谢,这非常有帮助。我还想要一些可以链接看似URL的东西的东西 - 作为一个基本要求,即使http://协议前缀不存在,它也会像www.yahoo.com这样链接。所以基本上,如果“www。” 它存在,它将链接它并假设它是http://。我还希望电子邮件变成mailto:links。示例:www.yahoo.com将转换为www.yahoo.com

这是我最终得到的代码(这个页面的代码和我在网上找到的其他东西的组合,以及我自己做的其他东西):

function Linkify(inputText) {
    //URLs starting with http://, https://, or ftp://
    var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    var replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with www. (without // before it, or it'd re-link the ones done above)
    var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    var replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links
    var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
    var replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText
}

在第二次替换中,(^ | [^ /])部分仅替换www.whatever.com,如果它还没有前缀为// - 以避免在第一次替换中已经链接了URL时进行双重链接。此外,www.whatever.com可能位于字符串的开头,这是正则表达式中该部分的第一个“或”条件。

这可以作为jQuery插件集成,如上面所示的Jesse P - 但我特别想要一个不在现有DOM元素上运行的常规函数​​,因为我正在使用我拥有的文本然后将它添加到DOM中,我希望在添加文本之前将文本“链接”,因此我将文本传递给此函数。效果很好。

作者: Travis 发布者: 2010 年 1 月 29 日

0

27615 作者的声誉

Travitron上面的回答中的电子邮件检测对我来说不起作用,因此我使用以下(C#代码)扩展/替换它。

// Change e-mail addresses to mailto: links.
const RegexOptions o = RegexOptions.Multiline | RegexOptions.IgnoreCase;
const string pat3 = @"([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,6})";
const string rep3 = @"<a href=""mailto:$1@$2.$3"">$1@$2.$3</a>";
text = Regex.Replace(text, pat3, rep3, o);

这允许使用“ firstname.secondname@one.two.three.co.uk ” 等电子邮件地址。

作者: Uwe Keim 发布者: 2010 年 2 月 12 日

7

97 作者的声誉

最好的脚本:http//benalman.com/projects/javascript-linkify-process-lin/

作者: FlycKER 发布者: 2010 年 6 月 25 日

140

1417 作者的声誉

我对Travis的代码进行了一些小修改(只是为了避免任何不必要的重新声明 - 但它对我的需求非常有用,非常好!):

function linkify(inputText) {
    var replacedText, replacePattern1, replacePattern2, replacePattern3;

    //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links.
    replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
    replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText;
}
作者: cloud8421 发布者: 2010 年 10 月 8 日

65

2175 作者的声誉

对Travis的Linkify()代码进行了一些优化。我还修复了一个错误,即子域类型格式的电子邮件地址不匹配(即example@domain.co.uk)。

另外,我将实现更改为String类的原型,以便可以像这样匹配项:

var text = 'address@example.com';
text.linkify();

'http://stackoverflow.com/'.linkify();

无论如何,这是脚本:

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses
        var emailAddressPattern = /[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim;

        return this
            .replace(urlPattern, '<a href="$&">$&</a>')
            .replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>')
            .replace(emailAddressPattern, '<a href="mailto:$&">$&</a>');
    };
}
作者: Roshambo 发布者: 2011 年 8 月 19 日

10

620 作者的声誉

我将Roshambo String.linkify()更改为emailAddressPattern以识别aaa.bbb。@ ccc.ddd地址

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses *** here I've changed the expression ***
        var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;

        return this
            .replace(urlPattern, '<a target="_blank" href="$&">$&</a>')
            .replace(pseudoUrlPattern, '$1<a target="_blank" href="http://$2">$2</a>')
            .replace(emailAddressPattern, '<a target="_blank" href="mailto:$1">$1</a>');
    };
}
作者: Christian Koch 发布者: 2011 年 8 月 21 日

4

5218 作者的声誉

如果您需要显示较短的链接(仅限域名),但使用相同的长URL,您可以尝试修改上面发布的Sam Hasler的代码版本

function replaceURLWithHTMLLinks(text) {
    var exp = /(\b(https?|ftp|file):\/\/([-A-Z0-9+&@#%?=~_|!:,.;]*)([-A-Z0-9+&@#%?\/=~_|!:,.;]*)[-A-Z0-9+&@#\/%=~_|])/ig;
    return text.replace(exp, "<a href='$1' target='_blank'>$3</a>");
}
作者: Artjom Kurapov 发布者: 2011 年 12 月 9 日

17

11146 作者的声誉

识别URL很棘手,因为它们通常被标点符号包围,并且因为用户经常不使用URL的完整形式。存在许多JavaScript函数用于替换带有超链接的URL,但是我无法找到一个urlize与基于Python的Web框架Django中的过滤器一样好的函数。因此我将Django的urlize函数移植到JavaScript:

https://github.com/ljosa/urlize.js

一个例子:

urlize('Go to SO (stackoverflow.com) and ask. <grin>', 
       {nofollow: true, autoescape: true})
=> "Go to SO (<a href="http://stackoverflow.com" rel="nofollow">stackoverflow.com</a>) and ask. &lt;grin&gt;"

第二个参数,如果为true,则导致rel="nofollow"插入。第三个参数,如果为true,则转义在HTML中具有特殊含义的字符。请参阅自述文件

作者: Vebjorn Ljosa 发布者: 2012 年 5 月 8 日

5

13724 作者的声誉

此解决方案与许多其他解决方案一样,并且实际上使用与其中一个相同的正则表达式,但是它不会返回HTML字符串,而是返回包含A元素和任何适用文本节点的文档片段。

 function make_link(string) {
    var words = string.split(' '),
        ret = document.createDocumentFragment();
    for (var i = 0, l = words.length; i < l; i++) {
        if (words[i].match(/[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi)) {
            var elm = document.createElement('a');
            elm.href = words[i];
            elm.textContent = words[i];
            if (ret.childNodes.length > 0) {
                ret.lastChild.textContent += ' ';
            }
            ret.appendChild(elm);
        } else {
            if (ret.lastChild && ret.lastChild.nodeType === 3) {
                ret.lastChild.textContent += ' ' + words[i];
            } else {
                ret.appendChild(document.createTextNode(' ' + words[i]));
            }
        }
    }
    return ret;
}

有一些警告,即旧的IE和textContent支持。

是一个演示。

作者: rlemon 发布者: 2012 年 11 月 22 日

0

87 作者的声誉

在从几个来源输入后,我现在已经找到了一个运行良好的解决方案。它与编写自己的替换代码有关。

答案

小提琴

function replaceURLWithHTMLLinks(text) {
    var re = /(\(.*?)?\b((?:https?|ftp|file):\/\/[-a-z0-9+&@#\/%?=~_()|!:,.;]*[-a-z0-9+&@#\/%=~_()|])/ig;
    return text.replace(re, function(match, lParens, url) {
        var rParens = '';
        lParens = lParens || '';

        // Try to strip the same number of right parens from url
        // as there are left parens.  Here, lParenCounter must be
        // a RegExp object.  You cannot use a literal
        //     while (/\(/g.exec(lParens)) { ... }
        // because an object is needed to store the lastIndex state.
        var lParenCounter = /\(/g;
        while (lParenCounter.exec(lParens)) {
            var m;
            // We want m[1] to be greedy, unless a period precedes the
            // right parenthesis.  These tests cannot be simplified as
            //     /(.*)(\.?\).*)/.exec(url)
            // because if (.*) is greedy then \.? never gets a chance.
            if (m = /(.*)(\.\).*)/.exec(url) ||
                    /(.*)(\).*)/.exec(url)) {
                url = m[1];
                rParens = m[2] + rParens;
            }
        }
        return lParens + "<a href='" + url + "'>" + url + "</a>" + rParens;
    });
}
作者: Mike Mestnik 发布者: 2013 年 11 月 4 日

2

2874 作者的声誉

注册: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]*)/ig

function UriphiMe(text) {
      var exp = /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]*)/ig; 
      return text.replace(exp,"<a href='$1'>$1</a>");
}

以下是一些测试字符串:

  1. 找到www.google.com
  2. 万维网
  3. 找到我的www。http://www.com
  4. 跟我来:http//www.nishantwork.wordpress.com
  5. http://www.nishantwork.wordpress.com
  6. 跟我来:http//www.nishantwork.wordpress.com
  7. https://stackoverflow.com/users/430803/nishant

注意:如果您不希望传递www为有效的,请使用以下注册码: /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig

作者: Nishant Kumar 发布者: 2014 年 1 月 30 日

306

68515 作者的声誉

决定

首先,滚动自己的正则表达式来解析URL是一个糟糕的主意。根据RFC,你必须想象这是一个常见的问题,有人为它编写,调试和测试了一个库。URI很复杂 - 请查看Node.js中的URL解析代码URI方案的Wikipedia页面。

在解析URL方面有很多边缘案例:国际域名,实际(.museum)与不存在(.etc)TLD,包括括号的奇怪标点符号,URL末尾的标点符号,IPV6主机名等。

我已经看了一吨图书馆,并有几个值得使用,尽管一些缺点:

我已经快速取消了这项任务资格的图书馆:

如果你坚持使用正则表达式,那么最全面的是来自ComponentURL regexp,尽管它会通过查看错误地检测到一些不存在的双字母TLD。

作者: Dan Dascalescu 发布者: 2014 年 2 月 21 日

2

663 作者的声誉

把事情简单化!说出你不能拥有的东西,而不是你拥有的东西:)

如上所述,URL可能非常复杂,尤其是在“?”之后,并非所有URL都以“www”开头。例如maps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

因此,不是有一个复杂的正则表达式,不会满足所有边缘情况,并且将难以维护,这个更简单的正如我在实践中运作良好。

比赛

http(s):// (anything but a space)+

www. (anything but a space)+

“任何事物”在哪里[^'"<>\s] ...基本上是一个贪婪的比赛,继续你的空间,报价,尖括号或行尾

也:

请记住检查它是否已经是URL格式,例如文本包含href="..."src="..."

添加ref = nofollow(如果适用)

这个解决方案并不像上面提到的库那样“好”,但是更简单,并且在实践中运行良好。

if html.match( /(href)|(src)/i )) {
    return html; // text already has a hyper link in it
    }

html = html.replace( 
            /\b(https?:\/\/[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='$1'>$1</a>" 
            );

html = html.replace( 
            /\s(www\.[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='http://$1'>$1</a>" 
            );

html = html.replace( 
             /^(www\.[^\s\(\)\'\"\<\>]+)/ig, 
            "<a ref='nofollow' href='http://$1'>$1</a>" 
            );

return html;
作者: Andrew Murphy 发布者: 2014 年 5 月 27 日

1

1798 作者的声誉

使用国际域和星体字符支持进行正确的URL检测并非易事。linkify-it库从许多条件构建正则表达式,最终大小约为6千字节:)。它比所有的lib更准确,目前在接受的答案中引用。

请参阅linkify-it演示以检查实时所有边缘情况并测试您的情况。

如果需要链接HTML源,则应首先解析它,并分别迭代每个文本标记。

作者: Vitaly 发布者: 2015 年 5 月 16 日

0

372 作者的声誉

使用HTML链接替换文本中的URL,忽略href / pre标记内的URL。 https://github.com/JimLiu/auto-link

作者: Jim Liu 发布者: 2015 年 6 月 11 日

1

1618 作者的声誉

我已经写了另一个JavaScript库,它可能对你更好,因为它非常敏感,误差最小,速度快,体积小。我目前正在积极维护它,所以请在演示页面中测试它,看看它对你有用。

链接:https//github.com/alexcorvi/anchorme.js

作者: Alex C. 发布者: 2016 年 3 月 2 日

6

748 作者的声誉

我在谷歌搜索了更新的东西并遇到了这个:

$('p').each(function(){
   $(this).html( $(this).html().replace(/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '<a href="$1">$1</a> ') );
});

演示: http //jsfiddle.net/kachibito/hEgvc/1/

适用于普通链接。

作者: degenerate 发布者: 2016 年 3 月 24 日

3

322 作者的声誉

应该注意关于URI复杂性的警告,但对你的问题的简单答案是:
要替换所有需要的/g标记,将标志添加到RegEx的末尾:
/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi

作者: Moritz 发布者: 2016 年 5 月 2 日

0

10246 作者的声誉

这是我的解决方案:

var content = "Visit https://wwww.google.com or watch this video: https://www.youtube.com/watch?v=0T4DQYgsazo and news at http://www.bbc.com";
content = replaceUrlsWithLinks(content, "http://");
content = replaceUrlsWithLinks(content, "https://");

function replaceUrlsWithLinks(content, protocol) {
    var startPos = 0;
    var s = 0;

    while (s < content.length) {
        startPos = content.indexOf(protocol, s);

        if (startPos < 0)
            return content;

        let endPos = content.indexOf(" ", startPos + 1);

        if (endPos < 0)
            endPos = content.length;

        let url = content.substr(startPos, endPos - startPos);

        if (url.endsWith(".") || url.endsWith("?") || url.endsWith(",")) {
            url = url.substr(0, url.length - 1);
            endPos--;
        }

        if (ROOTNS.utils.stringsHelper.validUrl(url)) {
            let link = "<a href='" + url + "'>" + url + "</a>";
            content = content.substr(0, startPos) + link + content.substr(endPos);
            s = startPos + link.length;
        } else {
            s = endPos + 1;
        }
    }

    return content;
}

function validUrl(url) {
    try {
        new URL(url);
        return true;
    } catch (e) {
        return false;
    }
}
作者: AndroidDev 发布者: 2018 年 7 月 24 日

0

240 作者的声誉

试试以下功能:

function anchorify(text){
  var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
  var text1=text.replace(exp, "<a href='$1'>$1</a>");
  var exp2 =/(^|[^\/])(www\.[\S]+(\b|$))/gim;
  return text1.replace(exp2, '$1<a target="_blank" href="http://$2">$2</a>');
}

alert(anchorify("Hola amigo! https://www.sharda.ac.in/academics/"));

作者: Moonis Abidi 发布者: 2019 年 3 月 12 日
32x32