用于验证DNS标签的正则表达式(主机名)

时间:2010-01-14 09:31:53

标签: regex validation forms dns expression

我想仅使用regualr表达式来验证主机名。

主机名(或DNS术语中的“标签”)传统上由RFC 952和RFC 1123定义,可能由以下有效字符组成。

列出项目

  • A到Z;大写字符
  • a到z;小写字符
  • 0到9;数字字符0到9
  • - ;破折号

规则说:

  • 主机名(标签)可以以字母或数字开头或结尾
  • 主持人姓名(标签)不得以' - '(破折号)
  • 开头或结尾
  • 主机名(标签)不得包含所有数值
  • 主机名(标签)最多可包含63个字符

您如何编写正则表达式来验证主机名?

7 个答案:

答案 0 :(得分:15)

^(?![0-9]+$)(?!-)[a-zA-Z0-9-]{,63}(?<!-)$

我使用Python编写的以下测试平台来验证它是否正常工作:

tests = [
    ('01010', False),
    ('abc', True),
    ('A0c', True),
    ('A0c-', False),
    ('-A0c', False),
    ('A-0c', True),
    ('o123456701234567012345670123456701234567012345670123456701234567', False),
    ('o12345670123456701234567012345670123456701234567012345670123456', True),
    ('', True),
    ('a', True),
    ('0--0', True),
]

import re
regex = re.compile('^(?![0-9]+$)(?!-)[a-zA-Z0-9-]{,63}(?<!-)$')
for (s, expected) in tests:
    is_match = regex.match(s) is not None
    print is_match == expected

答案 1 :(得分:12)

基于Marks答案的Javascript正则表达式:

pattern = /^(?![0-9]+$)(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$/g;

答案 2 :(得分:3)

值得注意的是,DNS标签和主机名组件的规则略有不同。最值得注意的是:'_'在主机名的任何组件中都不合法,但它是用于SRV记录之类的标签的标准部分。

更具可读性和便携性的方法是要求字符串匹配这些POSIX ERE的

^[[:alnum:]][[:alnum:]\-]{0,61}[[:alnum:]]|[[:alpha:]]$
^.*[[:^digit:]].*$

这些应该易于在任何标准兼容的ERE实现中使用。像Python示例中的Perl风格的回溯可以广泛使用,但是它的问题是它似乎无处不在。哎哟。

原则上可以在这两条线上制作一个ERE,但它会很长而且不实用。第一行处理除了全数字禁令之外的所有规则,第二行杀死那些规则。

答案 3 :(得分:3)

默认情况下,Ruby正则表达式是多行的,因此像Rails这样的东西警告不要使用^$。这是Mark对字符串字符安全开始和结束的回答:

\A(?![0-9]+$)(?!-)[a-zA-Z0-9-]{,63}(?<!-)\z

答案 4 :(得分:1)

根据此处的评论和我自己阅读的RFC 1035&amp; amp;修订的正则表达式1123:

Ruby:\A(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\z(下面的测试)

Python:^(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$(未经我测试)

Javascript:pattern = /^(?!-)[a-zA-Z0-9-]{1,63}$/g;(根据Tom Lime的回答,未经我测试)

试验:

tests = [
  ['01010', true],
  ['abc', true],
  ['A0c', true],
  ['A0c-', false],
  ['-A0c', false],
  ['A-0c', true],
  ['o123456701234567012345670123456701234567012345670123456701234567', false],
  ['o12345670123456701234567012345670123456701234567012345670123456', true],
  ['', false],
  ['a', true],
  ['0--0', true],
  ["A0c\nA0c", false]
]

regex = /\A(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\z/
tests.each do |label, expected|
  is_match = !!(regex =~ label)
  puts is_match == expected
end

说明:

  1. 感谢Mark Byers提供原始代码片段
  2. solidsnack指出RFC 1123允许全数字标签(https://tools.ietf.org/html/rfc1123#page-13
  3. RFC 1035不允许零长度标签(https://tools.ietf.org/html/rfc1035):<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
  4. 我添加了专门针对Ruby的测试,确保标签中没有嵌入新行。这要归功于ssorallen的笔记。
  5. 此代码可在此处获取:https://github.com/Xenapto/domain-label-validation - 如果您想要更新请求,我很乐意接受拉取请求。

答案 5 :(得分:1)

虽然接受的答案是正确的,RFC2181也在第11节中说明,&#34;名称语法&#34;:

  

DNS本身只对特定标签设置了一个限制   可用于识别资源记录。那一个限制   与标签的长度和全名有关。 [...]   DNS协议的实现不得有任何限制   在可以使用的标签上。特别是,DNS服务器不能   拒绝为区域提供服务,因为它包含可能不是的标签   某些DNS客户端程序可以接受。

这反过来意味着应该允许其他字符such as underscores

答案 6 :(得分:0)

k8s API 使用它用来验证的正则表达式进行响应,例如符合 RFC 1123 的字符串:

(⎈ minikube:default)➜  cloud-app git:(mc/72-org-ns-names) ✗ k create ns not-valid1234234$%
The Namespace "not-valid1234234$%" is invalid: metadata.name: 
Invalid value: "not-valid1234234$%": a lowercase RFC 1123 label must consist of lower case 
alphanumeric characters or '-', and must start and end with an alphanumeric character 
(e.g. 'my-name',  or '123-abc', regex used for validation is
 '[a-z0-9]([-a-z0-9]*[a-z0-9])?')