基于Bash的正则表达式域名验证

时间:2013-03-07 10:40:52

标签: regex bash dns

我想创建一个脚本,将新域添加到我们的DNS服务器。 我发现Fully qualified domain name validation REGEX。 但是,当我将它与sed一起使用时,它无法正常工作:

echo test | sed  '/(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(:[a-zA-Z]{2,})$)/p'  
--------
Output is: 
test
echo test.com | sed  '/(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(:[a-zA-Z]{2,})$)/p'  
--------
Output is: 
test.com

我预计第一个命令的输出应该是一个空行。 我做错了什么?

6 个答案:

答案 0 :(得分:9)

我发现这是一个更全面的正则表达式:

(?=^.{4,253}$)(^(?:[a-zA-Z0-9](?:(?:[a-zA-Z0-9\-]){0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$)

  • RFC 1034§3: 允许4-25 3 的长度,我知道的最短操作域," t.co"仍然匹配其他答案不在其中的地方。 255个字节是最大长度,减去每个标签的长度八位字节(TLD和"主要"子域)给我们253:(?=^.{4,253}$)
    • RFC 3696§2:技术上允许使用单字母TLD ,这意味着最小长度为3,但由于目前没有单字母TLD,因此最小长度为4是实用的。
  • RFC 1034§3:允许子域名中的数字,Conor Clafferty显然没有(通过不区分其他子域名"主要"子域名 - 即您注册的域名) - DNS规范没有'
  • RFC 1034§3:将单个标签限制为63个字符,允许中间使用连字符,同时限制字母数字的开头和结尾(?:[a-zA-Z0-9](?:(?:[a-zA-Z0-9\-]){,61}[a-zA-Z0-9])?\.)
  • 需要两个字母或更大的TLD [a-zA-Z]{2,}
    • RFC 3696§2:DNS规范在技术上允许TLD中的数字以及单字母TLD;但是,目前目前没有单字母TLD或TLD,并且不允许使用全数字TLD,因此这部分正则表达式已经简化。

答案 1 :(得分:2)

你的正则表达式中缺少一个问号:

(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+( :[a-zA-Z]{2,})$)

您可以测试正则表达式here

你可以用grep做你想做的事:

$ echo test.com | grep -P '(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)'
test.com
$ echo test | grep -P '(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)'
$

答案 2 :(得分:0)

皮埃尔 - 路易斯的回答对我来说并不适用。例如“小猫”被视为域名。 我添加了一个小调整,以确保域中至少有一个点。

(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+\.(?:[a-z]{2,})$)

在读取域的最后一部分之前,还需要额外的\.

答案 3 :(得分:0)

我知道没有sed实现支持您在该正则表达式中使用的各种Perl扩展。尝试使用Perl或grep -Ppcregrep,或将正则表达式简化为sed可以处理的内容。这是一个快速而肮脏的改编,它将正则表达式分成三个不同正则表达式的脚本,并在某些内容无法匹配时拒绝(或在最中间的情况下匹配)。

echo 'test' | sed -r '/^.{5,254}$/!d
    /^([^.]*\.)*[0-9]+\./d   # Seems incorrect; 112.com is valid
    /^([a-zA-Z0-9_\-]{1,63}\.?)+([a-zA-Z]{2,})$/!d'  # should disallow underscore
    # also, what's with the question mark after the literal dot?

这也完全无法接受IDNA域名(其中包含TLD中的破折号和数字等),所以我绝对不会推荐这一点,但希望它能告诉你如何将这样的内容改编为{{1}如果你愿意的话。

答案 4 :(得分:0)

我使用grep -P来执行此操作。

echo test | grep -P "^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$" 
--------
Output is: 

echo www.test.com | grep -P "^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$"
--------
Output is: www.test.com

答案 5 :(得分:-1)

如果该域必须存在,您可以尝试:

$ cat test.sh
#!/bin/bash

for h in "bert" "ernie" "www.google.com"
do
    host $h 2>&1 > /dev/null
    if [ $? -eq 0 ]
    then
        echo "$h is a FQDN"
    else
        echo "$h is not a FQDN"
    fi
done

jalderman@mba:/tmp$ ./test.sh 
bert is not a FQDN
ernie is not a FQDN
www.google.com is a FQDN