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

Dom*_*nic 106 regex validation domain-name

首先抱歉第10,000次RegEx问题,

我意识到还有其他与域相关的问题,但正则表达式要么不正常,要么太复杂,要么对于具有子域,协议和文件路径的URL.

我更简单,我需要验证一个域名:

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下的更多角色

非常感谢,相信我,我确实尝试过!

Tim*_*eld 74

我知道这是一个旧帖子,但是这里的所有正则表达式都缺少一个非常重要的组件:对IDN域名的支持.

IDN域名以xn--开头.它们在域名中启用扩展的UTF-8字符.例如,你知道"♡.com"是一个有效的域名吗?是的,"爱心点com"!要验证域名,您需要让http://xn--c6h.com/通过验证.

请注意,要使用此正则表达式,您需要将域转换为小写,并使用IDN库来确保将域名编码为ACE(也称为"ASCII兼容编码").一个好的库是GNU-Libidn.

idn(1)是国际化域名库的命令行界面.以下示例将UTF-8中的主机名转换为ACE编码.然后,生成的URL https://nic.xn--flw351e/可用作ACE编码的等效https:// nic.谷歌/.

  $ idn --quiet -a nic.??
  nic.xn--flw351e
Run Code Online (Sandbox Code Playgroud)

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

^((?!-))(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,})$
Run Code Online (Sandbox Code Playgroud)

选择域验证正则表达式时,您应该看到域是否与以下内容匹配:

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

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

看看Oracle公司国际语言环境指南国际化域名支持页面获取更多信息.

请随意在这里试用正则表达式:http://www.regexr.com/3abjr

ICANN保留了已委派的tld列表,可用于查看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,})$
Run Code Online (Sandbox Code Playgroud)

此正则表达式将停止在主机名末尾带有" - "的域,并将其标记为有效.此外,它允许无限的子域.

  • @timgws 但是,即使没有 `{1,1}`,任何字符或字符类或组也只会匹配一次。这就像写 `h{1,1}i{1,1}` 而不是 `hi` - 只会让阅读更难。 (2认同)
  • @FilipBartuzi 提到:“使用 IDN 库来确保将域名编码为 ACE”。它们实际上并不是有效的域名(DNS 仅支持字母和数字的子集,ACE/IDN 是它们发挥作用的原因)。 (2认同)
  • @Sandra `com.com` 是一个有效(且已注册!)的域名。因此它的任何子域也是有效的。此问答是关于验证域的**语法**,而不是验证它是否适合特定目的,也不是某人是否输入了“正确”的域。 (2认同)

pak*_*aka 47

我的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})$
Run Code Online (Sandbox Code Playgroud)

正则表达式可视化

https://www.debuggex.com/r/y4Xe_hDVO11bv1DV

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

  • 看起来很不错,但需要针对新TLD更新`{2,6}'标准.可能是`{2,}`. (9认同)
  • 两个替代方案的最后一部分也是错误的:存在接受IDNA子标签的ccTLD(两个字母).现在还存在已使用IDNA标签的TLD标签.你不应该特殊情况下最后一个与其他标签没有区别的标签(现在有许多扩展名添加了可变长度,jsut就像子域中的所有其他标签一样.注意IDNA标签也可能出现Punycoded(在这种情况下会有" - - "标签中的一个段,唯一的情况是标签中允许" - "最后,所有标签中的下划线无效. (3认同)

Cam*_*ron 41

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

/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/
Run Code Online (Sandbox Code Playgroud)

但请注意,这将拒绝许多有效的域名.

  • @infensus - 虽然根据您的规格,这个正则表达式是正确的,但您的规格是错误的.`g.co`是一个有效的域名,但`g`只是一个字符. (11认同)
  • @Neil:你是对的.原始问题要求3-63个字符(参见编辑3).它可以很容易地改为支持单字符域:`/ ^ [a-zA-Z0-9](?:[a-zA-Z0-9 - ] {0,61} [a-zA-Z0- 9])?\.[A-ZA-Z] {2,} $ /`.但这仍然拒绝了大量有效的东西...... (4认同)
  • 这应该符合我认为的所有情况:^([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})+ $ (3认同)
  • x.com 不会经过这里 (2认同)
  • 这甚至也不支持“.co.uk”顶级域名。 (2认同)

Yar*_*hiy 14

我打赌:

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

解释:

域名是根据细分构建的.这是一个部分(最终除外):

[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?
Run Code Online (Sandbox Code Playgroud)

它可以有1-63个字符,不以' - '开头或结尾.

现在追加'.' 到它并重复至少一次:

(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+
Run Code Online (Sandbox Code Playgroud)

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

[a-z0-9][a-z0-9-]{0,61}[a-z0-9]
Run Code Online (Sandbox Code Playgroud)

在此测试: http ://regexr.com/3au3g

  • 这确实是最好的正则表达式,不会偏离轨道。它可以处理单字符标签,可以处理 IDN 域(转换为 punycode),并且对 TLD 没有荒谬的长度要求。我认为您很难找到不匹配的域。它唯一不强制执行的是域的最大长度(253 个字符),但是可以轻松地将简单的长度检查与正则表达式一起使用。 (4认同)

小智 13

只是一个小小的修正 - 最后一部分应该达到6.因此,

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

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

  • 不会用新TLD切割它,例如`.photography` (15认同)
  • 注意:这不会传递有效(但很少见)的域名www.my---domain.com (3认同)
  • 不应检查TLD,它与子域没有区别。将正则表达式基于当前“可用”的tlds并不是未来的证明。 (3认同)
  • @SamFigueroa 你只需要修改它的长度 (2认同)

mky*_*ong 13

接受的答案不适合我,试试这个:

^(( - ?!)[A-ZA-Z0-9 - ] {1,63}(< - ?!)\)+ [A-ZA-Z] {2,6-} $

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

  • 不支持新的更长的TLD名称,如.audio,.photography,以及其中大部分...... http://data.iana.org/TLD/tlds-alpha-by-domain.txt (4认同)

And*_*zek 12

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

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

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

  • 最大长度为255个八位字节,包括长度前缀和空根.
  • 允许尾随'.' 用于显式dns根目录.
  • 允许服务域RR的前导'_',(错误:不对_标签强制执行15个字符最大值,也不要求至少一个域超过服务RR)
  • 匹配所有可能的TLD.
  • 不捕获子域标签.

按部件

Lookahead,使用可选的尾随文字'.'限制^ $到253个字符之间的最大长度.

(?=.{1,253}\.?$)
Run Code Online (Sandbox Code Playgroud)

Lookahead,下一个字符不是' - ',并且在下一个'.'之前没有'_'跟随任何字符.也就是说,强制标签的第一个字符不是' - ',只有第一个字符可能是'_'.

(?!-|[^.]+_)
Run Code Online (Sandbox Code Playgroud)

每个标签允许的字符数在1到63之间.

[A-Za-z0-9-_]{1,63}
Run Code Online (Sandbox Code Playgroud)

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

(?<!-)
Run Code Online (Sandbox Code Playgroud)

强制'.' 在每个标签的末尾,除了最后一个,它是可选的.

(?:\.|$)
Run Code Online (Sandbox Code Playgroud)

大部分从上面合并,这需要至少两个域级别,这不是很正确,但通常是合理的假设.如果您想允许TLD或不合格的相对子域(例如,localhost,myrouter,to.),请从{2,}更改为+.

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

此表达式的单元测试.

  • 谢谢!这是这里最好的正则表达式。你详尽的解释和单元测试是一个奖励。 (2认同)

Pet*_*erM 8

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

如果您需要以人类可读的形式验证IDN域,正则表达式将有所帮助.这允许匹配任何语言的任何字符.\p{L}

请注意,最后一部分也可能包含连字符!作为punycode编码的Chineese名称可能在tld中具有unicode字符.

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

  • google.com
  • masełkowski.pl
  • maselkowski.pl
  • m.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}]+$
Run Code Online (Sandbox Code Playgroud)

在这里检查和调整

注意:此正则表达式非常宽松,当前域名允许使用字符集.

更新:更简化,a-aA-Z\p{L}就像刚才一样\p{L}

注意2:唯一的问题是它会匹配其中带有双点的域......,就像mase?k..owski.pl.如果有人知道如何解决这个问题请改进.


Chr*_*ris 6

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

[域名 - 小写字母和0-9只] [可以有一个连字符] + [TLD - 只有小写,必须在2到7个字母之间]
http://rubular.com/非常适合测试正则表达式!
编辑:正如Dan Caddigan指出的那样,为'.rentals'更新了TLD最多7个字符.

  • 为什么要限制 TLD?现在“.photography”将无效。只需将其设置为无限字符或类似的东西即可。 (3认同)

zaT*_*cky 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})$
Run Code Online (Sandbox Code Playgroud)

后:

^(([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})$
Run Code Online (Sandbox Code Playgroud)


thi*_*ign 5

正如已经指出的那样,在实际意义上告诉子域(例如.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

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

By the books FQDN匹配(理论定义,实践中很少遇到):

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

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