如何在Javascript中替换不在href标签内的URL

5
我有一个情况,其中包含URL链接的文本。这些链接有两种形式:
1. www.stackoverflow.com 2. <a href="http://www.stackoverflow.com">Stack over flow</a>
我正在尝试创建一个简单的函数,使用正则表达式将所有类型为 1 的链接用 A HREF 标签包装起来,但保留其他已经包装好的链接。
我有类似这样的东西,但不成功。
function replaceURLWithHTMLLinks(text) {
    var exp = /(<(\s*)a(\s)*href.*>.*<\/(\s)*a(\s*)>)/ig;
    var matches = exp.exec(text);
    for(var i=0; i < matches.length; i++) {
        var line = matches[i];
        if(!exp.test(line)) {
            var exp2 = /(\b(?:(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[-A-Z0-9+&@#\/%=~_|$])|”(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)[^"\r\n]+”?|’(?:(?:https?|ftp|file):\/\/|www\.|ftp\.)[^'\r\n]+’?)/ig;
            text = text.replace("http://","");
                text = text.replace(exp2, "<a href=http://$1>$1</a>");
        }
    }

    return text;
}

它无法工作,但希望有人可以修复它 :)

编辑

在@MikeM的帮助下解决了问题。

function replaceLinksSO(text) {
    rex = /(<a href=")?(?:https?:\/\/)?(?:(?:www)[-A-Za-z0-9+&@#\/%?=~_|$!:,.;]+\.)+[-A-Za-z0-9+&@#\/%?=~_|$!:,.;]+/ig;   
    return text.replace(rex, function ( $0, $1 ) {
        if(/^https?:\/\/.+/i.test($0)) {
            return $1 ? $0: '<a href="'+$0+'">'+$0+'</a>';
        }
        else {
            return $1 ? $0: '<a href="http://'+$0+'">'+$0+'</a>';
        }
    });
}

可能是如何用链接替换普通URL?的重复问题。 - David
@Dve 不完全是重复的。我正在尝试仅在普通URL未包含href标签的情况下将其替换为链接。因为我是在HTML文档上进行操作。另一个正则表达式实际上完全未通过我的测试用例。 - george_h
2个回答

5

不需要分析上面复杂的正则表达式和函数,这里提供一个使用玩具URL匹配模式进行替换的示例实现,以说明如何进行此类替换。

var str = ' www.stackoverflow.com  <a href="http://www.somesite.com">somesite</a> www.othersite.org '
    rex = /(<a href=")?(?:https?:\/\/)?(?:\w+\.)+\w+/g;    

str = str.replace( rex, function ( $0, $1 ) {
    return $1 ? $0 : '<a href="' + $0 + '">' + $0 + '</a>';
});

你可以修改URL匹配模式,并根据需要插入例如\s*

很不错的解决方案,它成功地替换了字符串中所有的链接(并忽略了已经存在的链接)。不过我需要在 URL 前面添加 http://,否则链接会无效。 - george_h

1

将匹配/(https?:\/\/)?((?:www|ftp)\.[-A-Za-z0-9+&@#\/%?=~_|$!:,.;]+?)[\r\n\s]+/的模式替换为<a href="$1$2">$1</a>可以满足您的要求。

更好的正则表达式匹配是^(?!href="[^"\n\r\s]+?").*?(https?:\/\/)?((?:www|ftp)\.[-A-Za-z0-9+&@#\/%?=~_|$!:,.;]+)$


我没有注意到这一点。然而,这似乎不是一个非常健壮的处理方式。那么对于跟在URL后面的标点符号、右括号等呢?最好使用负回顾来确保它不是链接(或者更好的方法是将HTML解析器与正则表达式结合使用)。 - user1919238
@dan1111,但是JavaScript支持后顾吗? - Naveed S
这个方案可行,但它只匹配了我的测试字符串中的第一个链接。 - george_h
@george_h 你的输入文本是什么? - Naveed S
它只替换第一个链接,前三个“test”消失了。 - george_h
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接