什么是正则表达式,它将匹配没有子域的有效域名?


123

我需要验证域名:

google.com

stackoverflow.com

因此,以最原始的形式出现的域-甚至没有像www这样的子域。

  1. 字符只能是az | AZ | 0-9句点(。)和破折号(-)
  2. 域名部分不应以破折号(-)开头或结尾(例如-google-.com)
  3. 域名部分应在1到63个字符之间
  4. 目前,扩展名(TLD)可以是#1规则下的任何内容,我稍后可能会针对列表进行验证,尽管它应为1个或多个字符

编辑:TLD显然是2-6个字符

没有。修订4: TLD实际上应被标记为“子域”,因为它应包含.co.uk之类的东西-我想唯一可能的验证(除了检查列表之外)是“在第一个点之后应该有一个或规则1下的其他字符

非常感谢,相信我,我尝试了!


1
可能根本没有帮助。对于google.co.uk和某些日语域名,我敢肯定,在使用正则表达式之前,您必须三思。我个人认为,正则表达式不足以将域验证为真实域。仅供参考,这是TLD
Ayesh K

1
请参阅我对有关主机名验证的相关问题的回答。
SAM 2013年

2
经常被遗忘:对于完全限定域名,您应该在tld之后匹配一个句点。
schmijos

1
已经有4年了,现在这一数字已高达89,000
mydoglixu

1
这些答案中的一些非常好,但是在另一个问题上还有另一个很好的答案值得一看。
craftworkgames

Answers:


49

嗯,这是非常简单的一点点sneakier比它的外观(见注释),给予您的具体要求:

/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/

但是请注意,这将拒绝许多有效域。


很好,谢谢,这似乎很有效。您知道哪种域名不会通过验证?
多米尼克

12
@infensus-尽管鉴于您的规格,此正则表达式是正确的,但您的规格是错误的。g.co是有效的域名,但g只有一个字符。
sch 2012年

3
这应该符合我认为的所有情况:^([a-z0-9])(([a-z0-9-] {1,61})?[a-z0-9] {1})?(\。 [a-z0-9](([[a-z0-9-] {1,61})?[a-z0-9] {1})?)?(\。[a-zA-Z] {2 ,4})+ $
transilvlad13年

1
x.com不会在这里通过
Neil McGuigan

4
@Neil:你是对的。最初的问题要求输入3-63个字符(请参见编辑3)。可以很容易地更改它以支持一个字符的域:/^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.[a-zA-Z]{2,}$/。但这仍然会拒绝大量有效的东西……
Cameron

84

我知道这有点旧,但是这里的所有正则表达式都缺少一个非常重要的组成部分:对IDN域名的支持。

IDN域名以xn--开头。它们在域名中启用扩展的UTF-8字符。例如,您知道“♡.com”是有效域名吗?是的,“ love heart dot com”!要验证域名,您需要让http://xn--c6h.com/通过验证。

请注意,要使用此正则表达式,您需要将域转换为小写,并且还需要使用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

这个神奇的正则表达式应该涵盖大多数域(尽管我确信我错过了许多有效的边缘情况):

^((?!-))(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}\.[a-z]{2,})$

选择域验证正则表达式时,应查看域是否符合以下条件:

  1. xn--stackoverflow.com
  2. stackoverflow.xn--com
  3. stackoverflow.co.uk

如果这三个域均未通过,则您的正则表达式可能不允许使用合法域!

请查阅Oracle国际语言环境指南中的“国际化域名支持”页面,以获取更多信息。

请随时在此处尝试正则表达式:http : //www.regexr.com/3abjr

ICANN保留了已委派的顶级域名清单,可用于查看IDN域的一些示例。


编辑:

 ^(((?!-))(xn--|_{1,1})?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9][a-z0-9\-]{0,60}|[a-z0-9-]{1,30}\.[a-z]{2,})$

此正则表达式将阻止在主机名末尾带有“-”的域被标记为有效域。此外,它允许无限的子域。


1
请注意,这将仅支持最多一个子域,超出此范围将导致错误。除非将它用于内部站点等,否则您不会遇到任何诽谤。快速尝试允许它支持更多子域:/^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,}\.?((xn--)?([a-z0-9\-.]{1,61}|[a-z0-9-]{1,30})\.?[a-z]{2,})$/i
stakolee

1
但是寂寞的tld无法正常工作:(例如,to.to。)是具有内容的有效
URL。– iiic

@iiic,是的,但to.不是完全限定的域名。如果您想允许使用顶级域名,则应使用,如^(((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,1}\.)?(x--)?([a-z0-9\-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,})\.?$,但要注意,您也将允许输入类似test或的域名的人通过na
Tim Groeneveld

无效时接受invali.d为有效域名invali.d.co.uk
Pawel Krakowiak

1
应当注意,这xn--stackoverflow.com不是有效的名称,因为无法从Punycode转换“ stackoverflow”。但是,这超出了正则表达式所能做的。作为一项一般性评论,xn--[a-z0-9]+标签将IDN只,而xn--[a-z0-9]+\-[a-z0-9]+指示ASCII-和非ASCII字符的混合
马库斯

50

接下来是我的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

现在检查-_在启动或域标签的结束。


9
看起来不错,但是{2,6}需要为新TLD更新标准。大概吧{2,}
jwatts1980 2014年

@ jwatts1980是否有此类区域的示例?或者您是说未来可能的区域?
2014年

1
这是一篇文章讨论用实例和相关资源的链接即将发生的变化:zdnet.com/...
jwatts1980

1
为什么([a-zA-Z] {1} [a-zA-Z] {1})而不是([a-zA-Z] {2})?
安东

3
具有这两种选择的最后一部分也是错误的:存在接受IDNA子标签的ccTLD(两个字母)。现在还存在已经使用IDNA标签的TLD标签。您不应该对最后一个与其他标签没有区别的标签进行特殊处理(并且现在添加了许多扩展名,并且扩展名具有可变长度,就像子域中的所有其他标签一样。请注意,IDNA标签也可能显示为Punycoded(在这种情况下,会出现“- - ”在标签段,唯一的情况下‘ - ’允许在标签中。最后的底线是无效到处所有标签。
verdy_p

24

我的赌注:

^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$

解释:

域名是根据网段构建的。这是一个细分市场(决赛除外):

[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?

它可以包含1-63个字符,不能以“-”开头或结尾。

现在追加“。” 并重复至少一次:

(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+

然后附加最后一段,长度为2-63个字符:

[a-z0-9][a-z0-9-]{0,61}[a-z0-9]

在这里测试: http : //regexr.com/3au3g


@GaneshBabu完全匹配是什么意思?
Yaroslav Stavnichiy

1
所有其他答案都不适用于我,但这个答案可以。
丹尼·库洛姆贝

我有一个相似的要求,我想在最后尝试避免分号和逗号,但我尝试过很多,但下面没有成功的是我正在使用const regexDomain = / ^(?:[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] / g;好吧,它可以验证我是否使用和;介于两者之间,但最终无法通过验证。
哈里

我发现了几个应该有效但对您的正则表达式无效的域。例如редбулл.москва是有效域名,或者редбулл.рф和红色的公牛。中国
pubkey

1
@pubkey,您需要将这些域名转换为punycode。редбулл.москва的实际名称是xn--90afc0aazy.xn--80adxhks,而我的正则表达式与之匹配。
Yaroslav Stavnichiy

13

只是一个小的更正-最后一部分应为6。因此,

^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$

最长的TLD为museum(6个字符)-http: //en.wikipedia.org/wiki/List_of_Internet_top-level_domains


3
注意:这不会传递有效(但很少见)的域名www.my---domain.com
Chris Bier

17
不使用新的顶级域名(TLD)来削减它.photography
Sam Figueroa 2014年

2
@SamFigueroa您只需要修改它的长度
Steel Brain

3
不应检查TLD,它与子域没有区别。正则表达式基于当前的available顶级域名并不能证明未来。
卢瓦克福雷-Lacroix的

1
建议最后一位是{2,63}:看stackoverflow.com/questions/9238640/...
埃里克·多布斯

13

接受的答案对我不起作用,请尝试以下操作:

^((?!-)[A-Za-z0-9-] {1,63}(?<!-)\。)+ [A-Za-z] {2,6} $

请访问此单元测试用例进行验证。


4
不支持新的更长的TLD名称,例如.audio,.photography和其中的大多数... data.iana.org/TLD/tlds-alpha-by-domain.txt
mrbinky3000 2015年

@ mrbinky3000只需将最后一个更改为{2,6}其他内容即可。矿山:^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$
Mygod

@Mygod您的正则表达式包含超过最后一个问号的零宽度垃圾,因此任何复制它的人都会感到不愉快
MightyPork

1
@MightyPork你是对的!抱歉,这是一个(希望)干净的版本:^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$
Mygod '17

非常好。las,后向表达式在JavaScript中无效。:/
PhiLho

13

该答案适用于域名(包括服务RR),而不是主机名(例如电子邮件主机名)。

^(?=.{1,253}\.?$)(?:(?!-|[^.]+_)[A-Za-z0-9-_]{1,63}(?<!-)(?:\.|$)){2,}$

基本上,这是mkyong的答案,另外:

  • 最大长度为255个八位字节,包括长度前缀和空根。
  • 允许尾随“。” 用于显式dns根。
  • 允许在服务域RR的前导'_',(错误:不对_标签强加15个字符的最大值,也不需要在服务RR之上至少一个域)
  • 匹配所有可能的TLD。
  • 不捕获子域标签。

按零件

提前,将最大长度限制在^ $到253个字符之间,并带有可选的尾随文字'。'。

(?=.{1,253}\.?$)

向前看,下一个字符不是'-',并且在下一个'。'之前的任何字符后面都不能有'_'。也就是说,强制标签的第一个字符不是“-”,而只有第一个字符可以是“ _”。

(?!-|[^.]+_)

每个标签允许使用1到63个字符。

[A-Za-z0-9-_]{1,63}

在后面,前一个字符不是'-'。也就是说,强制标签的最后一个字符不是'-'。

(?<!-)

强制输入“。” 在每个标签的末尾(最后一个标签除外),该标签是可选的。

(?:\.|$)

通常需要从上面进行组合,这至少需要两个域级别,这不是很正确,但是通常是一个合理的假设。如果要允许TLD或不合格的相对子域通过(例如,localhost,myrouter等),请从{2,}更改为+。

(?:(?!-|[^.]+_)[A-Za-z0-9-_]{1,63}(?<!-)(?:\.|$)){2,}

为此表达式进行单元测试


1
谢谢!这是最好的正则表达式。您的详尽解释和单元测试是加分项。
naudster

“ RR”是什么意思?
惠勒

资源记录。通常是一个文本或信息字段,告诉您如何与服务进行交互。
Andrew Domaszek '17

此正则表达式不正确。例如,域redbull。移动有效,但正则表达式不匹配。
6

首先转换为punycode,然后进行匹配。前punycode版本的长度限制确实很难实现。
安德鲁·多马塞克

8

感谢您在其他答案中为域名验证解决方案指明正确的方向。域名可以通过各种方式进行验证。

如果您需要以易于阅读的形式验证IDN域,则正则表达式将为您提供帮助。这样可以匹配任何语言的任何字符。\p{L}

请注意,最后一部分也可能包含连字符!由于采用punycode编码的中文名称在tld中可能包含unicode字符。

我已经找到了匹配的解决方案,例如:

  • google.com
  • masełkowski.pl
  • maselkowski.pl
  • maselkowski.pl
  • www.masełkowski.pl.com
  • xn--masekowski-d0b.pl
  • 中国互联网络信息中心。中国
  • xn--fiqa61au8b7zsevnm8ak20mc4a87e.xn--fiqs8s

正则表达式是:

^[0-9\p{L}][0-9\p{L}-\.]{1,61}[0-9\p{L}]\.[0-9\p{L}][\p{L}-]*[0-9\p{L}]+$

在这里检查和调整

注意:此正则表达式是允许的,因为当前域名允许使用字符集。

更新:更加简化,a-aA-Z\p{L}与只是\p{L}

注意2:唯一的问题是它将匹配其中带有双点的域...,例如masełk..owski.pl。如果有人知道如何解决此问题,请改进。


我们可以使用[:alpha:][:digit]代替\p{L}。它工作正常。
puchu

如果不先将IDN转换为punycode,就无法以这种方式验证IDN。例如,对于您的expr,中国互联网络信息中心中国互联网络信息中心中国互联网络信.中国检查是否有效,但在IDN转换后,每个标签的字节过多。\ p {L}匹配符号,而不是punycode字节(每个符号不同),因此,在尝试限制其转换后大小时,重复计数无济于事。
Andrew Domaszek '18

好一点,每个部分限制为64个字节。但是,我们无法使用RegExp进行检查,因此需要使用punycode解码器进行进一步的验证步骤-如果您的示例主机名失败,则将失败。中国人必须为此受到限制。
PeterM '18年

7
^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,7}$

[域-小写字母,仅0-9。] [可以有连字符] + [TLD-小写字母,必须在2至7个字母之间。]
http://rubular.com/非常适合测试正则表达式!
编辑:正如Dan Caddigan指出的那样,“。rentals”的TLD最大值已更新为7个字符。


1
为什么要限制TLD?现在.photography将无效。使其成为无限字符或类似的东西即可。
adriaan

5

没有足够的代表对此发表评论。为了响应paka的解决方案,我发现我需要调整三个项目:

  • 破折号和下划线被移动,因为破折号被解释为范围(如“ 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})$

3

对于新gTLD

/^((?!-)[\p{L}\p{N}-]+(?<!-)\.)+[\p{L}\p{N}]{2,}$/iu

2
请向我们提供更多详细信息,您回答的内容将比其他内容更好吗?您还匹配什么?请直接编辑您的信息以添加信息。
Sven R.

就像我写的那样:新gTLD。具有Unicode字符和Unicode TLD的域。
本基尔2016年

1
@BenKeil:这是什么部分约为:(< - !)
约旦

@jor是负面的背后。看看这个快捷方式
foo.com/app/dojos/regex/cheatsheet

3

正如已经指出的,从实际意义上讲子域(例如.co.uk域)并不明显。我们使用此正则表达式来验证出现在野外的域。它涵盖了我所知道的所有实际用例。欢迎新的。根据我们的指南,它避免了非捕获组和贪婪匹配。

^(?!.*?_.*?)(?!(?:[\d\w]+?\.)?\-[\w\d\.\-]*?)(?![\w\d]+?\-\.(?:[\d\w\.\-]+?))(?=[\w\d])(?=[\w\d\.\-]*?\.+[\w\d\.\-]*?)(?![\w\d\.\-]{254})(?!(?:\.?[\w\d\-\.]*?[\w\d\-]{64,}\.)+?)[\w\d\.\-]+?(?<![\w\d\-\.]*?\.[\d]+?)(?<=[\w\d\-]{2,})(?<![\w\d\-]{25})$

证明,解释和示例:https ://regex101.com/r/FLA9Bv/9注:当前仅在Chrome中有效,因为regex使用仅在ECMA2018中受支持的lookbehinds

验证域时,有两种方法可供选择。

按书进行FQDN匹配(理论上的定义,在实践中很少遇到):

实用/保守FQDN匹配(实用定义,在实践中应得到预期和支持):

  • 符合以下例外/补充规定的书本
  • 有效字符: [a-zA-Z0-9.-]
  • 标签不能以连字符开头或结尾(根据RFC-952RFC-1123 / 2.1
  • TLD的最小长度为2个字符,最大长度为24个字符(根据当前记录)
  • 不匹配尾随点


2

这是带有示例的完整代码:

<?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

2
^((localhost)|((?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,253})$

谢谢@mkyong作为我回答的基础。我已经对其进行了修改,以支持更长的可接受标签。

同样,“本地主机”在技术上也是有效的域名。我将修改此答案以适应国际化域名。


0
/^((([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])则此正则表达式将予以解决。

如果我们要进行至少一次匹配,+则将使用该匹配。


0

^ [a-zA-Z0-9] [-a-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"



0

以下正则表达式提取给定域的子,根和tld:

^(?<domain>(?<domain_sub>(?:[^\/\"\]:\.\s\|\-][^\/\"\]:\.\s\|]*?\.)*?)(?<domain_root>[^\/\"\]:\s\.\|\n]+\.(?<domain_tld>(?:xn--)?[\w-]{2,7}(?:\.[a-zA-Z-]{2,3})*)))$

已针对以下域进行了测试:

* stack.com
* sta-ck.com
* sta---ck.com
* 9sta--ck.com
* sta--ck9.com
* stack99.com
* 99stack.com
* sta99ck.com
* google.com.uk
* google.co.in

* google.com
* masełkowski.pl
* maselkowski.pl
* m.maselkowski.pl
* www.masełkowski.pl.com
* xn--masekowski-d0b.pl
* xn--fiqa61au8b7zsevnm8ak20mc4a87e.xn--fiqs8s

* xn--stackoverflow.com
* stackoverflow.xn--com
* stackoverflow.co.uk

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.