我需要在JavaScript中计算字符串中链接的长度和数量。
以下是我要做的一个例子:
var myString = 'Lorem ipsum dolor sit amet, www.google.com/abc consectetur adipiscing elit. http://stackoverflow.com/question/ask Donec sed magna ultricies.'
function getLinkLength(myString) {
// do stuff. ha!
return linkArray; // returns [0] => 18, [1] => 37
}
输出应该告诉我字符串中所有链接的长度,如下所示:
www.google.com/abc = 18
http://stackoverflow.com/question/ask = 37
你能帮我解析链接的字符串并返回每个字符串的长度吗?电子邮件地址也应视为链接(例如email@domain.com = 16)。
这是一个字符计数器,我不想惩罚链接长度的字符,所以我需要减去字符串中所有链接的长度。
以下是我想要使用的一些正则表达式。我意识到这些并不完美,但如果我能处理基本链接,我就会牺牲角落的情况。
regexes.email = /^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/;
regexes.url = /^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2}))|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/i;
regexes.cc = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,
regexes.urlsafe = /^[^&$+,\/:=?@ <>\[\]\{\}\\^~%#]+$/;
答案 0 :(得分:2)
您的网址正则表达式看起来既可能是严重的过度杀戮,也可能会错过某些案例。
最好使用更简单的URL正则表达式(除非您有明确的理由需要该特定模式)。
这是一个JSFiddle,可以解决这个问题:http://jsfiddle.net/m5ny4/1/
var input = "http://google.com google.com/abc pie@pie.com cookies@some.longer.domain www.cookies.com ftps://a.b.c.d/cookies someone@gmail.com";
var pattern = /(?:[^\s]+@[a-z]+(\.[a-z]+)+)|(?:(?:(?:[a-z]+:\/\/)|\s)[a-z]+(\.[a-z]+)+(\/[^\s]*)?)/g;
var matches = input.match(pattern);
for (var i = 0, len = matches.length; i < len; i++) {
$('ul').append('<li>' + matches[i] + " = " + matches[i].length + '</li>');
}
我使用的模式既是电子邮件又是网址,但与上面显示的模式相比大大简化了。它可以减少一点(将它们更紧密地结合起来),但我选择将它们分开并将它们组合在一起,因为它更容易阅读。
正则表达式基本上有两大块:(?:[^\s]+@[a-z]+(\.[a-z]+)+)
和(?:(?:(?:[a-z]+:\/\/)|\s)[a-z]+(\.[a-z]+)+(\/[^\s]*)?)
第一个块是电子邮件。忽略围绕它的(?: )
包裹,你有[^\s]+@[a-z]+(\.[a-z]+)+
。 [^\s]+
匹配@符号前的任何非空白字符。更改后,它会将任何域名与任意数量的子域名或顶级域名(例如google.com,google.co.uk)进行匹配。
第二个(?:(?:(?:[a-z]+:\/\/)|\s)[a-z]+(\.[a-z]+)+(\/[^\s]*)?)
是网址。第一个有意义的部分是(?:[a-z]+:\/\/)|\s)
,它可以匹配任何协议或空白字符(告诉它起始的位置)。如果要将其限制为某些协议,则只需将[a-z]+
替换为所需的协议。
接下来是[a-z]+
,它与第一个(子)域匹配,后跟(\.[a-z]+)+
匹配一个或多个其他域(因为您至少需要两个域才能创建合法的域名)。最后,我们有(\/[^\s]*)
可选地匹配所有内容,直到找到空格。
其余的很简单。全局匹配(模式结尾处的g
)以获取所有匹配项,然后循环遍历它们并在字符串上使用.length
来获取它们的长度。
我只是将它们输出到列表中,但你可以通过替换for循环来做任何你想做的事。