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

当前回答

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

其他回答

对我有用:

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

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

以下是我的解决方案:

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;
    }
}

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

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

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


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

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

/ig;

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

经过几个来源的输入,我现在有一个很好的解决方案。这与编写自己的替换代码有关。

的答案。

小提琴。

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