146

我需要验证一个域名:

google.com

stackoverflow.com

因此,最原始形式的域 - 甚至不是像 www 这样的子域。

  1. 字符只能是az | 亚利桑那州| 0-9点(.) 和破折号(-)
  2. 域名部分不应以破折号 (-) 开头或结尾(例如 -google-.com)
  3. 域名部分的长度应介于 1 到 63 个字符之间
  4. 扩展名 (TLD) 目前可以是 #1 规则下的任何内容,稍后我可能会根据列表验证它们,但它应该是 1 个或多个字符

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

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

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

4

23 回答 23

106

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

IDN 域名以 xn-- 开头。它们在域名中启用扩展的 UTF-8 字符。例如,您知道“♡.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保留一份已授权的 tld 列表,可用于查看 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,}$

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

于 2014-11-18T06:08:55.783 回答
63

好吧,鉴于您的特定要求,它比看起来更简单(请参阅评论):

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

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

于 2012-04-24T22:07:55.363 回答
51

我的正则表达式是下一个:

^[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

现在它检查-_在域标签的开头或结尾。

于 2013-11-18T11:45:24.707 回答
31

我的赌注:

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

于 2015-05-02T21:50:53.983 回答
18

此答案适用于域名(包括服务 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 和 to),请从 {2,} 更改为 +。

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

此表达式的单元测试

于 2016-12-16T23:16:07.927 回答
15

接受的答案对我不起作用,试试这个:

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

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

于 2014-09-08T04:33:57.013 回答
14

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

于 2013-06-04T15:45:05.707 回答
9
^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,7}$

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

于 2013-05-23T13:27:49.660 回答
8

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

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

请注意,最后一部分也可能包含连字符!由于 punycode 编码的中文名称可能在 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}]+$

在这里检查和调整

注意:此正则表达式非常宽松,当前域名允许的字符集也是如此。

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

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

于 2016-07-20T09:46:09.793 回答
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})$
于 2014-07-03T11:41:14.183 回答
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,因为正则表达式使用仅在 ECMA2018 中受支持的lookbehinds

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

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

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

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

对于新 gTLD

/^((?!-)[\p{L}\p{N}-]+(?<!-)\.)+[\p{L}\p{N}]{2,}$/iu
于 2016-03-11T09:14:17.030 回答
2
^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]+(\.[a-zA-Z]+)$
于 2012-04-24T22:10:36.490 回答
2
^((localhost)|((?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,253})$

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

此外,“localhost”在技术上是一个有效的域名。我将修改此答案以适应国际化域名。

于 2015-08-05T02:54:33.837 回答
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
于 2017-06-27T12:05:33.497 回答
1

^[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"

于 2015-06-12T13:43:13.243 回答
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]),这个正则表达式会处理这个问题。

如果我们想进行至少一次匹配,+就会用到。

于 2015-04-02T10:34:33.380 回答
0

很简单,很随意。它会有像-notvalid.at-all这样的误报,但不会有误报。

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

它确保它有一系列可以以点结尾的字母数字和破折号,然后是任意数量的此类序列。

我喜欢这个正则表达式的地方:它很短(可能是这里最短的),易于理解,并且足以在客户端验证用户输入错误。

于 2020-11-03T02:27:48.427 回答
0
  • ^((?!-))(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 - 沙盒

于 2019-12-10T13:06:23.940 回答
0

我做了以下操作来简单地获取域以及协议。示例: https ://www.facebook.com/profile/user/ftp: //182.282.34.337/movies/M

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

将为您提供输出: https ://www.facebook.com/ftp: //192.282.34.337/

于 2020-07-25T07:56:34.210 回答
0

以下正则表达式提取给定域的 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
于 2019-12-30T20:14:12.723 回答
0

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

方法:isFQDN(str [, options])

于 2021-03-03T11:49:48.830 回答
0

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

\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b
于 2022-01-08T07:31:41.107 回答