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

当前回答

应该注意关于URI复杂性的警告,但对您的问题的简单回答是: 要替换每个匹配项,你需要在RegEx的末尾添加/g标志: / (\ b (https ? | | ftp文件):\ / \ [-A-Z0-9 +&@#\/%?=~_|!:,.;]*[- A-Z0-9 +&@#\/%=~_|])/ 胃肠道

其他回答

我将Roshambo String.linkify()更改为emailaddressppattern以识别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>');
    };
}

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

如上所述,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;

这样做的最佳脚本: http://benalman.com/projects/javascript-linkify-process-lin/

上面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”这样的电子邮件地址。

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

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

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