使用RegEx进行域名validation

首先对于第一个RegEx问题抱歉,

我意识到还有其他领域相关的问题,但是正则expression式要么不能正常工作,要么太复杂,要么用于具有子域名,协议和文件path的URL。

我的更简单,我需要validation一个域名:

google.com

stackoverflow.com

因此,一个域的forms – 甚至不是像www这样的子域名。

  1. 字符只能是az | AZ | 0-9周期 (。)和短划线 ( – )
  2. 域名部分不应以破折号( – )开头或结尾(例如-google-.com)
  3. 域名部分应该在1到63个字符之间
  4. 扩展名(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.mewow.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式时,您应该看看域是否符合以下内容:

  1. xn--stackoverflow.com
  2. stackoverflow.xn – COM
  3. 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"