是否有一种快速而肮脏的方法来验证是否输入了正确的FQDN?请记住,没有DNS服务器或Internet连接,因此必须通过regex/awk/sed进行验证。
有什么想法吗?
(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-).)+[a-zA-Z]{2,63}$)
regex充其量只能是类似的东西,而且规则会随着时间的推移而变化。上面的regex是在考虑以下内容的情况下编写的,并且特定于主机名-
主机名由一系列用点连接的标签组成。每个标签的长度为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提供了regex的另一种破解方法,使TLD的规范成为可选:
(?=^.{1,253}$)(^(((?!-)[a-zA-Z0-9-]{1,63}(?<!-))|((?!-)[a-zA-Z0-9-]{1,63}(?<!-).)+[a-zA-Z]{2,63})$)
- 911-有效
- 911.gov-有效
编辑2:有人要求提供一个在js中工作的版本。它在js中不起作用的原因是js不支持regex look-behind。特别是代码(?<!-)
-指定前一个字符不能是连字符。
不管怎样,在这里,它被重写了,没有后备——有点丑,但没有太多
(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9].)+[a-zA-Z]{2,63}$)
你同样可以在约翰·里克斯的版本上进行类似的替换。
编辑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-fully-qualified-domain-name.html
然而,在我使用的各种工具中,使用拖尾点似乎会导致一些不可预测的结果,因此建议我要小心。
如今,随着域名国际化和数千(!)个新的顶级域名,情况变得更加艰难。
简单的部分是,您仍然可以在"上拆分组件&";。
您需要一个可注册TLD的列表。有一个网站:
https://publicsuffix.org/list/effective_tld_names.dat
您只需要检查ICANN认可的。注意一个可注册TLD可以有不止一个组件;co.uk";。
然后是IDN和punycode。域现在是Unicode。例如,
"xn-nnx388a";相当于";臺灣&";。顺便提一下,这两个都是有效的顶级域名。
有关punycode转换代码,请参阅";http://golang.org/src/pkg/net/http/cookiejar/punycode.go"。
检查每个域组件的语法也有新的规则。参见RFC5890https://www.rfc-editor.org/rfc/rfc5890
组件可以是A-标签(仅限ASCII)或Unicode。ASCII标签要么遵循旧语法;xn-";,在这种情况下,他们是一个流氓Unicode字符串的版本。
Unicode的规则非常复杂,在RFC5890中给出了这些规则。这些规则旨在防止字符从左到右和从右到左混合。
对不起,没有简单的答案。
这个正则表达式就是您想要的:
(?=^.{1,254}$)(^(?:(?!d+.)[a-zA-Z0-9_-]{1,63}.?)+(?:[a-zA-Z]{2,})$)
它匹配您的示例域(groupa-zone1appserver.example.com或cod.eu等)
我试着解释一下:
(?=^.{1,254}$)
匹配长度在1到254个字符之间的域名(可以以任何字符开头),如果我们假设co.uk是最小长度,它也可能是5254。
(^
开始匹配
(?:
定义匹配组
(?!d+.)
域名不应该由数字组成,因此1234.co.uk或abc.123.uk不被接受,而1a.ko.uk是。
[a-zA-Z0-9_-]
域名应由只有a-zA-Z0-9_-的单词组成
{1,63}
任何域级别的长度最大为63个字符,(可能是2,63)
+
和
(?:[a-zA-Z]{2,})$)
域名的最后一部分不应后跟任何其他单词,并且必须由至少2个字符的单词a-zA-Z 组成
我们使用此正则表达式来验证出现在野外的域。它涵盖了我所知道的所有实际用例。欢迎新的。根据我们的指导方针,它避免了非捕获组和贪婪匹配。
^(?!.*?_.*?)(?!(?:[w]+?.)?-[w.-]*?)(?![w]+?-.(?:[w.-]+?))(?=[w])(?=[w.-]*?.+[w.-]*?)(?![w.-]{254})(?!(?:.?[w-.]*?[w-]{64,}.)+?)[w.-]+?(?<![w-.]*?.[d]+?)(?<=[w-]{2,})(?<![w-]{25})$
证明和解释:https://regex101.com/r/FLA9Bv/40
验证域时有两种方法可供选择。
根据书籍FQDN匹配(理论定义,在实践中很少遇到):
- 最大253个字符长(根据RFC-1035/3.1、RFC-2181/11)
- 每个标签最多63个字符长(根据RFC-1035/3.1、RFC-2181/11)
- 允许使用任何字符(根据RFC-2181/11)
- TLD不能全部为数字(根据RFC-3696/2)
- FQDN可以以完整的形式编写,其中包括根区域(尾随点)
实用/保守的FQDN匹配(实用定义,在实践中预期和支持):
- 通过与以下例外/添加匹配的书籍
- 有效字符:
[a-zA-Z0-9.-]
- 标签不能以连字符开头或结尾(根据RFC-952和RFC-1123/2.1)
- TLD最小长度为2个字符,根据当前现有记录,最大长度为24个字符
- 与尾随点不匹配
上面的正则表达式既包含书本上的规则,也包含实用规则。
考虑事项#1:
请注意,由于RFC-2181中放宽了要求,DNS标签几乎可以由任何符号组合组成(然而,长度限制仍然存在):
"任何可以用作任何资源记录标签的二进制字符串。DNS协议的实现不得对可使用的标签设置任何限制。特别是,DNS服务器不得拒绝为某个区域提供服务,因为该区域包含某些DNS客户端程序可能无法接受的标签";(https://www.rfc-editor.org/rfc/rfc2181#section-11)
考虑#2:
";还有一个附加规则,它本质上要求顶级域名不全是数字"(https://www.rfc-editor.org/rfc/rfc3696#section-2)
考虑到这两个因素,正确的正则表达式如下所示:
/^(?!://)(?=.{1,255}$)((.{1,63}.){1,127}(?![0-9]*$)[a-z0-9-]+.?)$/i
查看演示@http://regexr.com/3g5j0
以下表达式
(^((?=^.{4,253}$)(((http){0,1}|(http){0,1}|(ftp){0,1}|(ws){0,1})(s{0,1})://){0,1})((((?!-)[pL0-9-]{1,63})(?<!-)(.)){1,})(((?!-)[a-z0-9-]{1,63})(?<!-)((/{0,1}[pLpN?=-]*)+){1})$)
将匹配
https://www.tes1t.com/lets/to?878932572
https://www.test.co.uk/lets/to?878932572
http://www.test.com/lets/to?878932572
http://www.test.co.uk/lets/to?878932572
ftp://www.test.com/lets/to?878932572
subdomain.test.com/lets/to?878932572
subdomain.test.com/lets/to?878932572
subdomain.subdomain.test.net/lets/to?878932572
sub-domain.test.net/lets/to?878932572
sub-domain.test.net/lets-go/to?878932572
www.test.net/lets/to?878932572
www.test-test.com/
www.test-test.com
subdomain.subdomainsubdomainsuèdomainsubdomainsubdomainsubdomainsubdomain.net/let2s/to?=878932572
www.test-test.co.uk
http://www.test-test-.com/test
www.test-teèst.co.uk/lets
www.test-test.co.uk/lets/
www.test-test.co.uk/lets/to?
test-test.co.uk/lets/to?
test-test.co.uk/lets/
test-test.co.uk/lets
test-test.co.uk
http://test.com/lets/to?878932572
https://test.com/lets/to?878932572
ftp://test.com/lets/to?878932572
ftps://test.com/lets/to?878932572
ws://test.com/lets/to?878932572aa
wss://test.com/lets/to?=878932572bar
test.com
subdomain.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.khbdomainsubdomainsubdomain.test.net/lets/to?87893257
但不匹配:
www.-test-fail-.com
www.-test-fail.com
-test-fail.com
test-fail-.com
subdomain.subdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomainubdomainsubdomainsubdomain.test.net/lets/to?878932572
subdomain.subdomainsubdomainsubdcnvcnvcnofhfhghgfhvnhj-mainsubdomainsubdohhghghghfhgffgjh-gfhfdhfdghmainsubdocgvhngvnbnbmghghghaihgfjgfnfhfdghgsufghgghghhdfjgffsgfbdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomain.test.net/lets/to?878932572
subdomain.test.test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test.khbdomainsubdomainsubdomain.test.net/lets/to?87893257