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

当前回答

对我有用:

var urlRegex =/(\b((https?|ftp|file):\/\/)?((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3}))(\:\d+)?(\/[-a-z\d%_.~+]*)*(\?[;&a-z\d%_.~+=-]*)?(\#[-a-z\d_]*)?)/ig;

return text.replace(urlRegex, function(url) {
    var newUrl = url.indexOf("http") === -1 ? "http://" + url : url;
    return '<a href="' + newUrl + '">' + url + '</a>';
});

其他回答

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

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

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


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

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

/ig;

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

我不得不做相反的事情,并使html链接只是URL,但我修改了你的正则表达式,它的工作就像一个魅力,谢谢:)

var exp = /<a\s.*href=['"](\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])['"].*>.*<\/a>/ig;

source = source.replace(exp,"$1");

识别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文件。

对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检测与国际域名和星体字符支持不是微不足道的事情。Linkify-it库从许多条件构建正则表达式,最终大小约为6千字节:)。它比目前在公认答案中引用的所有lib都更准确。

看到linkify-it演示检查所有的边缘情况和测试你的。

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