我正在使用下面的函数来匹配给定文本中的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>"); 
}

当前回答

我还编写了另一个JavaScript库,它可能对您更好,因为它非常敏感,误报最少,速度快,规模小。我目前正在积极维护它,所以请在演示页面中测试它,看看它是如何为你工作的。

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

其他回答

用链接替换url(一般问题的答案)

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

Dan Dascalescu的回答是URL匹配库的最佳总结 (截至2014年2月)


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

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

/ig;

但这只修复了正则表达式只替换第一个匹配的问题。不要使用那个代码。

对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>');
    };
}

保持简单!说你不能拥有的,而不是你能拥有的。

如上所述,url可能相当复杂,特别是在'?',并不是所有的都以'www '开头,例如maps.bing.com/something?key=!"£$%^*()&lat=65&lon&lon=20

所以,与其有一个不满足所有边缘情况的复杂正则表达式,而且很难维护,不如用这个更简单的正则表达式,它在实践中对我来说很好。

匹配

http(s)://(除空格外的任何字符)+

www。(除了空格)+

Where 'anything' is [^'"<>\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;

试试下面的函数:

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/“));

识别URL很棘手,因为它们经常被标点符号包围,而且用户经常不使用URL的完整形式。有很多JavaScript函数可以用超链接替换url,但我在基于python的web框架Django中找不到一个像urlize过滤器一样好用的。因此,我将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;"

第二个参数如果为真,则会插入rel="nofollow"。如果第三个参数为真,则转义HTML中具有特殊含义的字符。请参阅README文件。