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

当前回答

我在谷歌上搜索了最新的消息,发现了这个:

$('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/

工作真的很好,正常的链接。

其他回答

谢谢,这对我很有帮助。我还希望能够链接看起来像URL的东西——作为基本需求,它将链接类似www.yahoo.com的东西,即使没有http://协议前缀。所以基本上,如果“www.”存在,它就会链接它,并假设它是http://.我还想让电子邮件变成mailto:链接。示例: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,我希望文本是“链接”之前,我添加它,所以我通过这个函数传递文本。伟大的工作。

这个解决方案的工作原理和其他许多解决方案一样,实际上使用了与其中一个相同的正则表达式,但是它将返回一个包含a元素和任何适用文本节点的文档片段,而不是返回HTML String。

 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支持。

这里是一个演示。

上面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源代码,则应该首先解析它,然后分别迭代每个文本标记。

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