这应该很简单,但这使我难以理解。无论有没有协议(protocol),有没有www,都有很多匹配正则表达式的好坏方法。我的问题是(在javascript中):如果我使用正则表达式来匹配文本字符串中的URL,并将其设置为仅与“domain.com”匹配,它还会捕获电子邮件地址的域( “@”后面的部分),我不希望这样。负向查找可以解决问题-但显然在JS中无法解决。
到目前为止,这是我最近的成功:
/^(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g
但是如果匹配不在字符串的开头,则失败。而且我敢肯定我会以错误的方式解决它。哪里有简单的答案?
编辑:修改后的正则表达式以回应以下一些评论(坚持以“www”开头,而不是允许子域:
\b(www\.)?([^@])(\w*\.)(\w{2,3})(\.\w{2,3})?(\/\S*)?$
但是,如评论中所述,这仍然与@之后的域匹配。
谢谢
最佳答案
这是因为比赛开始时的^
:/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g
js> "www.foobar.com".match(/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g)
["www.foobar.com"]
js> "aoeuaoeu foobar.com".match(/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g)
[" foobar.com"]
js> "toto@aoeuaoeu foobar.com".match(/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g)
[" foobar.com"]
js> "toto@aoeuaoeu toto@foobar.com".match(/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g)
["foobar.com"]
尽管它仍与域前的空格匹配。而且它对域做出了错误的假设……
xyz.example.org
是与您的正则表达式不匹配的有效域; www.3x4mpl3.org
是与您的正则表达式不匹配的有效域; example.co.uk
是与您的正则表达式不匹配的有效域; ουτοπία.δπθ.gr
是与您的正则表达式不匹配的有效域。 什么定义合法域名?它只是由点分隔的utf-8字符序列。它不能有两个点接一个,标准名称是
\w\.\w\w
(因为我认为不存在一个字母tld)。不过,我要做的是简单地匹配所有看起来像域的东西,方法是使用单词边界(
\b
)将所有带有点分隔符的文本作为文本:/\b(\w+\.)+\w+\b/g
js> "aoe toto.example.org uaoeu foo.bar aoeuaoeu".match(/\b(\w+\.)+\w+\b/g)
["toto.example.org", "foo.bar"]
js> "aoe toto@example.org toto.example.org uaoeu foo.bar aoeuaoeu".match(/\b(\w+\.)+\w+\b/g)
["example.org", "toto.example.org", "foo.bar"]
js> "aoe toto@example.org toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/\b(\w+\.)+\w+\b/g)
["example.org", "toto.example.org", "foo.bar", "f00bar.com"]
然后进行第二轮检查,在找到的域列表中该域是否确实存在。缺点是javascript中的正则表达式无法检查unicode字符,并且
\b
或\w
都不会接受ουτοπία.δπθ.gr
作为有效域名。在ES6中,有
/u
modifier,它可以与最新的浏览器一起使用(但到目前为止我还没有测试过):"ουτοπία.δπθ.gr aoe toto@example.org toto.example.org uaoeu foo.bar aoeuaoeu".match(/\b(\w+\.)+\w+\b/gu)
编辑:
是的,它将:为了跳过所有电子邮件地址,下面是正则表达式实现的工作原理:
/(?![^@])?\b(\w+\.)+\w+\b/g
js> "aoe toto@example.org toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/(?<![^@])?\b(\w+\.)+\w+\b/g)
["toto.example.org", "foo.bar", "f00bar.com"]
尽管它与unicode相同...但很快就会在JS中出现...
解决这个问题的唯一方法是,将
@
实际保留在匹配的正则表达式中,并丢弃任何包含@的匹配项:js> "toto.net aoe toto@example.org toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/@?\b\w+\.+\w+\b/g).map(function (x) { if (!x.match(/@/)) return x })
["toto.net", (void 0), "toto.example", "foo.bar", "f00bar.com"]
或使用ES6 / JS1.7中的新列表理解功能,该功能应在现代浏览器中使用…
[x for x of "toto.net aoe toto@example.org toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/@?\b\w+\.+\w+\b/g) if (!x.match(/@/))];
最后更新:
/@?\b(\w*[^\W\d]+\w*\.+)+[^\W\d_]{2,}\b/g
> "x.y tot.toc.toc $11.00 11.com 11foo.com toto.11 toto.net aoe toto@example.org toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/@?\b(\w*[^\W\d]+\w*\.+)+[^\W\d_]{2,}\b/g).filter(function (x) { if (!x.match(/@/)) return x })
[ 'tot.toc.toc',
'11foo.com',
'toto.net',
'toto.example.org',
'foo.bar',
'f00bar.com' ]