(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$)
正则表达式最多只能是此类事情的近似值,并且规则会随着时间而变化。上述正则表达式是在编写时考虑到以下几点并且特定于主机名-
主机名由一系列用点连接的标签组成。
每个标签的长度为 1 到 63 个字符,并且可能包含:
- ASCII 字母 a-z(不区分大小写),
- 数字0-9,
- 和连字符 ('-')。
此外:
- 标签不能以连字符开头或结尾 (RFC 952)
- 标签可以以数字开头(RFC 1123)
- 包括点在内的 ascii 主机名的最大长度为 253 个字符(不包括尾随点)
(http://blogs.msdn.com/b/oldnewthing/archive/2012/04/12/10292868.aspx)
- 主机名中不允许使用下划线(但在其他 DNS 类型中允许)
一些假设:
- TLD 至少包含 2 个字符,并且只有 a-z
- 我们希望至少比 TLD 高 1 级
结果:有效/无效
- 911.gov - 有效
- 911 - 无效(无 TLD)
- a-.com - 无效
- -a.com - 无效
- a.com - 有效
- a.66-无效
- my_host.com - 无效(下划线)
- 典型主机名33.whatever.co.uk - 有效
编辑:
John Rix 提供了一种正则表达式的替代方案,使 TLD 规范成为可选:
(?=^.{1,253}$)(^(((?!-)[a-zA-Z0-9-]{1,63}(?<!-))|((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63})$)
编辑2:
有人要求提供一个可以在 js 中运行的版本。
它在 js 中不起作用的原因是因为 js 不支持正则表达式查找后面。
具体来说,代码(?<!-)
- 指定前一个字符不能是连字符。
不管怎样,这里是在没有lookbehind的情况下重写的——有点丑,但不多
(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)
您同样可以对 John Rix 的版本进行类似的替换。
编辑3:如果你想允许尾随点 - 这在技术上是允许的:
(?=^.{4,253}\.?$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}\.?$)
我不熟悉尾随点语法,直到 @ChaimKut 指出它们并且我做了一些研究
- http://dns-sd.org./TrailingDotsInDomainNames.html
- https://jdebp.eu./FGA/web-complete-qualified-domain-name.html
然而,在我使用的各种工具中,使用尾随点似乎会导致一些不可预测的结果,所以我建议谨慎一些。