使用RegEx进行域名validation
首先对于第一个RegEx问题抱歉,
我意识到还有其他领域相关的问题,但是正则expression式要么不能正常工作,要么太复杂,要么用于具有子域名,协议和文件path的URL。
我的更简单,我需要validation一个域名:
google.com
stackoverflow.com
因此,一个域的forms – 甚至不是像www这样的子域名。
- 字符只能是az | AZ | 0-9和周期 (。)和短划线 ( – )
- 域名部分不应以破折号( – )开头或结尾(例如-google-.com)
- 域名部分应该在1到63个字符之间
-
扩展名(TLD)现在可以是#1规则下的任何东西,我可以稍后在列表中validation它们,它应该是1个或更多个字符
编辑:TLD显然是2-6个字符
没有。 4修改: TLD实际上应该被标记为“子域”,因为它应该包括像.co.uk这样的东西 – 我想可能唯一的validation(除了检查列表)将是“后第一个点应该有一个规则#1下的更多字符
非常感谢,相信我,我尝试了!
那么,根据你的具体要求,它看起来相当简单 ,看上去有点偷偷摸摸(见评论):
/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/
但请注意,这将拒绝很多有效的域名。
我的RegEx是下一个:
^[a-zA-Z0-9][a-zA-Z0-9-_]{0,61}[a-zA-Z0-9]{0,1}\.([a-zA-Z]{1,6}|[a-zA-Z0-9-]{1,30}\.[a-zA-Z]{2,3})$
可以用i.oh1.me和wow.british-library.uk
UPD
这是更新的规则
^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$
https://www.debuggex.com/r/y4Xe_hDVO11bv1DV
现在它在域标签的开始或结束处检查-
或_
。
我知道这是一个旧post,但是这里的所有正则expression式都缺less一个非常重要的组件:对IDN域名的支持。
IDN域名以xn--开头。 它们在域名中启用扩展的UTF-8字符。 例如,你知道“♡.com”是一个有效的域名吗? 是的,“爱心点com”! 要validation域名,您需要让http://xn--c6h.com/通过validation。;
请注意,要使用此正则expression式,您需要将域转换为小写,并使用IDN库来确保您将域名编码为ACE(也称为“ASCII兼容编码”)。 一个好的库是GNU-Libidn。
idn(1)是国际化域名库的命令行界面。 以下示例将UTF-8中的主机名转换为ACE编码。 然后,生成的URL https://nic.xn--flw351e/可用作https:// nic。谷歌/的 ACE编码等效项。
$ idn --quiet -a nic.谷歌nic.xn--flw351e
这个神奇的正则expression式应该覆盖大部分领域(尽pipe我确信有很多我错过的有效边缘案例):
^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,1}\.(xn--)?([a-z0-9\-]{1,61}|[a-z0-9-]{1,30}\.[az]{2,})$
select域validation正则expression式时,您应该看看域是否符合以下内容:
- xn--stackoverflow.com
- stackoverflow.xn – COM
- stackoverflow.co.uk
如果这三个域名不通过,您的正则expression式可能不允许合法域名!
请参阅Oracle国际语言环境指南中的“国际化域名支持”页面以获取更多信息。
随意尝试在这里的正则expression式: http : //www.regexr.com/3abjr
互联网名称与数字地址分配机构(ICANN)保留已委派的域名列表,可用于查看IDN域名的一些示例。
编辑:
^(((?!-))(xn--)?[a-z0-9-_]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9\-]{1,61}|[a-z0-9-]{1,30}\.[az]{2,})$
此正则expression式将停止在主机名末尾具有“ – ”的域被标记为有效。 另外,它允许无限的子域名。
只是一个小小的更正 – 最后一部分应该是6。因此,
^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[az]{2,6}$
最长的TLD是museum
(6个字符) – http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
接受的答案不适合我,试试这个:
^(( – ?!)[A-ZA-Z0-9 – ] {1,63}(< – ?!)\)+ [A-ZA-Z] {2,6-} $
访问此unit testing用例进行validation。
我的赌注:
^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$
解释:
域名是根据段build立的。 这是一个部分(除了最后):
[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?
它可以有1-63个字符,不以“ – ”开始或结束。
现在追加'。' 至less重复一次:
(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+
然后附上长度为2-63个字符的最后一段:
[a-z0-9][a-z0-9-]{0,61}[a-z0-9]
在这里testing: http : //regexr.com/3au3g
这个答案是为域名(包括服务的RR),而不是主机名称(如电子邮件主机名)。
^(?=.{1,253}\.?$)(?:(?!-|[^.]+_)[A-Za-z0-9-_]{1,63}(?<!-)(?:\.|$)){2,}$
基本上是mkyong的回答 ,另外:
- 最大长度为255个八比特组,包括长度前缀和空根。
- 允许跟踪“。” 为显式的dns根。
- 允许为服务域RR提供前导'_'(错误:不对_标签强制执行15个字符,也不要求服务RR上方至less有一个域)
- 匹配所有可能的TLD。
- 不捕获子域标签。
按部分
超前,限制最大长度在^ $到253个字符之间,可选的结尾字符'。'
(?=.{1,253}\.?$)
前面看,下一个字符不是' – ',在下一个'。'之前没有任何字符。 也就是说,强制标签的第一个字符不是“ – ”,只有第一个字符可能是“_”。
(?!-|[^.]+_)
每个标签允许的字符数在1到63之间。
[A-Za-z0-9-_]{1,63}
往后看,以前的angular色不是' – '。 也就是说,强制标签的最后一个字符不是' – '。
(?<!-)
强制一个'。' 在除了最后一个标签之外的每个标签的末尾,它是可选的。
(?:\.|$)
从上面大多数情况下,这需要至less两个域级别,这是不正确的,但通常是一个合理的假设。 如果您希望允许TLD或非限定的相关子域通过(例如localhost,myrouter),则从{2,}更改为+。
(?:(?!-|[^.]+_)[A-Za-z0-9-_]{1,63}(?<!-)(?:\.|$)){2,}
unit testing这个expression式。
感谢您在其他答案中指出正确的方向在域名validation解决scheme。 域名可以通过各种方式进行validation。
如果您需要以可读的formsvalidationIDN域,regex \p{L}
将会有所帮助。 这允许匹配任何语言的任何字符。
请注意, 最后一部分也可能包含连字符 ! 由于punycode编码中文名称可能在tld中有unicode字符。
我已经解决了这个问题,例如:
- google.com
- masełkowski.pl
- maselkowski.pl
- m.maselkowski.pl
- http://www.masełkowski.pl.com
- xn--masekowski-d0b.pl
- 中国互联networking信息中心。中国
- XN – fiqa61au8b7zsevnm8ak20mc4a87e.xn – fiqs8s
正则expression式是:
^[0-9\p{L}][0-9\p{L}-\.]{1,61}[0-9\p{L}]\.[0-9\p{L}][\p{L}-]*[0-9\p{L}]+$
检查并调谐在这里
注:这个正则expression式是相当宽容的,因为是目前的域名允许字符集。
更新 :更简化,因为a-aA-Z\p{L}
与\p{L}
注2:唯一的问题是,它会匹配域中的双点…,就像masełk..owski.pl
。 如果有人知道如何解决这个问题,请改善。
没有足够的代表还没有评论。 为了回应帕卡的解决scheme,我发现我需要调整三个项目:
- 短划线和下划线由于短划线被解释为一个范围而移动(如在“0-9”中)
- 添加了许多子域名的句号
- 将TLD的潜在时间延长至13
之前:
^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$
后:
^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][-_\.a-zA-Z0-9]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,13}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$
^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[az]{2,6}$
[域名 – 小写字母和只有0-9] [可以有连字符] + [顶级域名 – 只有小写,必须在2和6个字母之间]
http://rubular.com/是testing正则expression式的绝佳select!;
编辑:如ahadinyoto指出,更新TLD最多6个字符。
^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]+(\.[a-zA-Z]+)$
这里是完整的例子代码:
<?php function is_domain($url) { $parse = parse_url($url); if (isset($parse['host'])) { $domain = $parse['host']; } else { $domain = $url; } return preg_match('/^(?!\-)(?:[a-zA-Z\d\-]{0,62}[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63}$/', $domain); } echo is_domain('example.com'); //true echo is_domain('https://example.com'); //true echo is_domain('https://.example.com'); //false echo is_domain('https://localhost'); //false
对于新gTLD
/^((?!-)[\p{L}\p{N}-]+(?<!-)\.)+[\p{L}\p{N}]{2,}$/iu
^((localhost)|((?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,253})$
谢谢@mkyong我的答案的基础。 我已经修改它以支持更长的可接受的标签。
另外,“localhost”在技术上是一个有效的域名。 我将修改这个答案,以适应国际化的域名。
/^((([a-zA-Z]{1,2})|([0-9]{1,2})|([a-zA-Z0-9]{1,2})|([a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]))\.)+[a-zA-Z]{2,6}$/
-
([a-zA-Z]{1,2})
– >只接受两个字符。 -
([0-9]{1,2})
– >只接受两个数字
如果超过了两个([a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9])
这个正则expression式就会处理这个问题。
如果我们想要至less进行一次匹配+
将被使用。
^ [A-ZA-Z0-9] [ – α-ZA-Z0-9] + [A-ZA-Z0-9] [AZ] {2,3}。([AZ] {2,3})。 ?([AZ] {2,3})?$
工作的例子:
stack.com sta-ck.com sta---ck.com 9sta--ck.com sta--ck9.com stack99.com 99stack.com sta99ck.com
它也将用于扩展
.com.uk .co.in .uk.edu.in
不会工作的例子:
-stack.com
即使是最长的域名扩展名".versicherung"