我正在使用下面的函数来匹配给定文本中的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>");
}
我将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>');
};
}
Reg例:
/ (\ b ((https ? | | ftp文件):\ \ / | (www)) [-A-Z0-9 +&@#\/%?=~_|!:,.;]*[- A-Z0-9 +&@#\/%=~_|]*)/ 搞笑
function UriphiMe(text) {
var exp = /(\b((https?|ftp|file):\/\/|(www))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]*)/ig;
return text.replace(exp,"<a href='$1'>$1</a>");
}
下面是一些测试字符串:
请登录www.google.com找我
www
请登录www.http://www.com找我
请关注我:http://www.nishantwork.wordpress.com
http://www.nishantwork.wordpress.com
请关注我:http://www.nishantwork.wordpress.com
https://stackoverflow.com/users/430803/nishant
注意:如果你不想将www作为有效的传递,请使用下面的reg ex:
/ (\ b ((https ? | | ftp文件):\ \ / | (www)) [-A-Z0-9 +&@#\/%?=~_|!:,.;]*[- A-Z0-9 +&@#\/%=~_|])/ 搞笑
以下是我的解决方案:
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;
}
}
首先,滚动自己的regexp来解析url是一个糟糕的想法。您必须想象这是一个足够常见的问题,根据rfc,有人已经为它编写、调试和测试了一个库。URI是复杂的——查看Node.js中URL解析的代码和关于URI方案的维基百科页面。
在解析URL时,有大量的边缘情况:国际域名,实际的(.museum)和不存在的(.etc)顶级域名,奇怪的标点符号(包括括号),URL末尾的标点符号,IPV6主机名等。
我已经查看了大量的库,尽管有一些缺点,但还是有一些值得使用:
Soapbox的linkify已经投入了大量精力,2015年6月的一次重大重构删除了jQuery依赖项。它仍然存在idn问题。
AnchorMe是一个自称更快更精简的新产品。还有一些IDN问题。
Autolinker.js列出了非常具体的特性(例如:将正确处理HTML输入。该实用程序不会改变anchor()标签内的href属性”)。当演示版本可用时,我将对其进行一些测试。
我很快就取消了这个任务的库:
Django的urlize不能正确处理某些tld(以下是官方列出的有效tld)。没有演示。
autolink-js不会检测“www.google.com”没有http://,,所以它不太适合自动链接“随意的url”(没有方案/协议)在纯文本中找到。
本·阿尔曼的链接自2009年以来就没有维护过。
如果坚持使用正则表达式,最全面的是Component中的URL regexp,尽管它会错误地检测到一些不存在的双字母tld。