如何用链接替换纯URL?

JavaScript

Itachi小哥

2020-03-13

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

第1522篇《如何用链接替换纯URL?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

9个回答
梅十三 2020.03.13

这是我的解决方案:

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;
    }
}
古一JinJin 2020.03.13

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

Gil村村 2020.03.13

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 ”。

神乐路易 2020.03.13

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

回答

小提琴

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;
    });
}
西门理查德 2020.03.13

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

西门小卤蛋 2020.03.13

具有国际域名和星体字符支持的正确URL检测并不是一件容易的事。linkify-it库根据许多条件构建正则表达式,最终大小约为6 KB :)。它比目前接受的答案中引用的所有库更准确。

请参阅linkify-it演示以检查所有边缘情况并测试您的情况。

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

村村凯 2020.03.13

我已经写了另一个JavaScript库,它对您可能会更好,因为它非常敏感,并且误报率极低,而且体积小巧。我目前正在积极维护它,因此请在演示页面上对其进行测试,并查看它如何为您工作。

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

Mandy梅Green 2020.03.13
StafanJim 2020.03.13

用链接替换URL(常见问题的答案)

问题中的正则表达式遗漏了很多边缘情况。检测URL时,最好使用专门的库来处理国际域名,.museumURL内和末尾的新TLD(如,括号和其他标点符号)以及许多其他情况。有关其他一些问题的说明,请参见Jeff Atwood的博客文章“ URL问题”。

URL匹配库最佳摘要Dan Dascalescu的答案+100
(截至2014年2月)


“使一个正则表达式替换多个匹配项”(针对特定问题的答案)

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

/ig;

但这只能解决正则表达式仅替换第一个匹配项的问题。不要使用该代码。

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android