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

我需要验证一个域名:

Google.com

Stackoverflow.com

因此,一个最原始的域名——甚至不是像 www 这样的子域名。

  1. 字符只能是 A-Z | A-Z | 0-9句号(.)以及 Dash(-)
  2. 域名部分不应以破折号(-) (例如 -google-.com)开始或结束
  3. 域名部分的长度应该在1到63个字符之间
  4. 扩展名(TLD)目前可以是 # 1规则下的任何内容,稍后我可以根据列表验证它们,但它应该是1个或更多个字符

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

修订第4号: TLD 实际上应该被标记为“子域”,因为它应该包括。Co.uk ——我认为唯一可能的验证(除了对列表进行检查之外)是“在第一个点之后,应该有一个或多个字符符号在规则 # 1之下”

非常感谢,相信我,我尽力了!

339352 次浏览

嗯,它的 非常直截了当比它看起来要隐秘一点(见注释) ,考虑到你的具体要求:

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

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

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

[域-小写字母和0-9只][可以有一个连字符] + [ TLD-小写只,必须在2至7个字母长]
Http://rubular.com/ 在测试正则表达式方面非常出色!
编辑: 更新 TLD 最多为7个字符的’。租赁’,丹卡迪根指出。

只是一个小小的修正-最后一部分应该是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

接下来是我的正则表达式:

^[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})$

我欠你一个人情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})$

Regular expression visualization

Https://www.debuggex.com/r/y4xe_hdvo11bv1dv

现在它在域标签的开始或结束处检查 -_

对于帕卡的解决方案,我发现我需要调整三个项目:

  • 破折号和下划线被移动,因为破折号被解释为一个范围(如在“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-Za-z0-9-]{1,63}(? < ! -) + [ A-Za-z ]{2,6} $

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

我知道这是一篇老文章,但是这里的所有正则表达式都缺少一个非常重要的组件: 对 IDN 域名的支持。

IDN 域名 以 xn-开头。它们在域名中启用扩展的 UTF-8字符。例如,你知道“ & quot; something.com”是一个有效的域名吗?是啊“爱心.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. Stackoverflow.com
  2. Stackoverflow. xn —— com
  3. Stackoverflow.co.uk

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

查看 Oracle 国际语言环境指南中的国际化域名支持页面了解更多信息。

欢迎在这里尝试正则表达式: 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})\.[a-z]{2,}$

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

/^((([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]),这个正则表达式会处理。

如果我们想做匹配至少一次 +将被使用。

我打赌:

^(?:[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]

在这里测试: < a href = “ http://regexr.com/3au3g”rel = “ norefrer”> http://regexr.com/3au3g

^ [ a-zA-Z0-9][-a-zA-Z0-9] + [ a-zA-Z0-9] . [ a-z ]{2,3}(. [ a-z ]{2,3}) ? (. [ a-z ]{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"

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

谢谢@mkyong 作为我回答的基础。我已经修改了它来支持更长的可接受的标签。

另外,“ localhost”在技术上是一个有效的域名。

新的通用顶级域名

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

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

如果您需要验证 身份识别码域的 人类可读性形式,正则表达式 \p{L}将有所帮助。这允许匹配任何语言中的任何字符。

请注意,最后一部分可能包含连字符也! 作为普尼码编码的中文名称可能在 tld 中有 Unicode 字符。

我想到了一个解决方案,比如:

  • Google.com
  • Mase Kowski
  • Maselkowski
  • M.maselkowski.pl
  • Www.mase kowski. pl.com
  • Masekowski-d0b.pl
  • 中国互联网络信息中心
  • Xn —— fiqa61au8b7zsevnm8ak20mc4a87e.xn —— fiqs8

正则表达式是:

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

检查并调整这里

注意: 这个 regexp 是相当宽松的,因为当前域名允许字符集。

更新 : 更加简化,因为 a-aA-Z\p{L}\p{L}是一样的

注2: 唯一的问题是,它将匹配域与双点在它... ,如 masełk..owski.pl。如果有人知道如何解决这个问题,请改进。

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

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

它基本上是 Mkyong 的回答,另外:

  • 最大长度为255个八位字节,包括长度前缀和空根。
  • 为显式 dns 根目录允许拖尾’.’。
  • 对服务域 RR 允许前导“ _”(bug: 对 _ label 不强制执行15个字符的最大值,也不需要服务域 RR 之上的至少一个域)
  • 匹配所有可能的顶级域名。
  • 不捕获子域标签。

按部分

向前看,将 ^ $之间的最大长度限制为253个字符,可选的尾随文字’

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

向前看,下一个字符不是“-”,下一个“”之前的任何字符后面都没有“ _”.也就是说,强制要求标签的第一个字符不是“-”,只有第一个字符可以是“ _”。

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

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

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

回看,前一个字符不是“-”。也就是说,强制标签的最后一个字符不是“-”。

(?<!-)

在每个标签的末尾强制使用 a’. ,除了最后一个标签,其中 a’是可选的。

(?:\.|$)

大多数情况下,这需要至少两个领域级别,这不是很正确,但通常是一个合理的假设。如果希望允许 TLD 或非限定的相对子域通过(例如,localhost、 myrouter,以.) ,则从{2,}更改为 +

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

正如已经指出的,在实际意义上讲子域(例如 .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 中使用,因为正则表达式使用了仅在 ECMA2018中支持的后退功能)

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

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

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

  • 与下列异常/补充相匹配的按部就班的方法
  • 有效字符: [a-zA-Z0-9.-]
  • 标签不能以连字符开始或结束(根据 RFC-952RFC-1123/2.1)
  • TLD 最小长度为2个字符,最大长度为24个字符,根据当前存在的记录
  • 跟尾点不吻合
  • ^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,}\.?((xn--)?([a-z0-9\-.]{1,61}|[a-z0-9-]{0,30})\.[a-z-1-9]{2,})$

编码后将验证诸如 яндекс.рф这样的域。

Https://regex101.com/r/hf8wfm/1 -沙盒

下面的正则表达式提取给定域的 sub、 root 和 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

我做了以下简单的获取域连同协议。 例如: Https://www.facebook.com/profile/user/ Ftp://182.282.34.337/books/M

使用下面的正则表达式模式: [ a-zA-Z0-9] + ://. * ?/

会给你输出: Https://www.facebook.com/ Ftp://192.282.34.337/

非常简单,非常宽松。它会有像 - 完全没有-完全没有这样的假阳性,但不会有假阴性。

/^([0-9a-z-]+\.?)+$/i

它确保它有一个字母数字和破折号的序列,可以以一个点结束,并在它之后,任何数量的这类序列。

我喜欢 regexp 的一点是: 它很短(可能是这里最短的) ,易于理解,并且足以在客户端验证用户输入错误。

对于 Javascript,您可以查看验证程序库: Https://www.npmjs.com/package/validator

方法: isFQDN(str [, options])

检查域的每个部分是否不超过63个字符,并允许使用 Punycode 符号的国际化域名:

\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b