2014-01-16 64 views
3

我想为只匹配有效域的grep做一个正则表达式。grep有效的域正则表达式

我的版本的工作还算不错,但符合以下无效域:

@subdom..dom.ext 

这里是我的正则表达式:

echo "@dom.ext" | grep "^@[[:alnum:]]\+[[:alnum:]\-\.]\+[[:alnum:]]\+\.[[:alpha:]]\+\$" 

我使用bash工作,所以我逃特殊字符。

样品应符合:

@subdom.dom.ext 
@subsubdom.subdom.dom.ext 
@subsub-dom.sub-dom.ext 

感谢您的帮助

+0

如果有必要准确grep和比赛唯一的现有顶级域名的,看看https://stackoverflow.com/questions/14460680/how-to-get-a- list-of-tlds-using-bash-for-building-a-regex –

回答

6

一个真正完整的解决方案需要更多的工作,但这里有一个镜头(注意,@前缀假设):

^@(([a-zA-Z](-?[a-zA-Z0-9])*)\.)*[a-zA-Z](-?[a-zA-Z0-9])+\.[a-zA-Z]{2,}$ 

你可以用egrep(或grep -E)使用,也可与[[ ... =~ ... ]],bash的正则表达式匹配运算符。

做以下假设,它比实际的DNS名称的限制更宽松:

  • 只有ASCII(非外资)字母被允许 - 请参阅下面的国际化域名(IDN)的考虑;还有,IDN的ASCII形式 - 例如xn--bcher-kva.chbücher.ch) - 不匹配(尽管它很容易解决)。
  • 对嵌套子域的数量没有限制。
  • 对任何标签(名称组件)的长度没有限制,对名称的总长度没有限制(实际限制见here)。
  • TLD(最后一个组件)仅由字母组成,其长度至少为2.
  • 子域和域名都必须以字母开头;该域名的长度必须至少为2;子域允许为单字母。

下面是一个简单的测试:

for d in @subdom..dom.ext @dom.ext @subdom.dom.ext @subsubdom.subdom.dom.ext @subsub-dom.sub-dom.ext; do 
[[ $d =~ \ 
    ^@(([a-zA-Z](-?[a-zA-Z0-9])*)\.)*[a-zA-Z](-?[a-zA-Z0-9])+\.[a-zA-Z]{2,}$ \ 
]] && echo YES || echo NO 
done 

支持Internationalized Domain Names (IDN)

一个简单的改进,也符合国际化域名是在[[:alnum:]][[:alpha:]][a-zA-Z0-9]更换[a-zA-Z]以上正则表达式;即:

^@(([[:alpha:]](-?[[:alnum:]])*)\.)*[[:alpha:]](-?[[:alnum:]])+\.[[:alpha:]]{2,}$ 

注意事项

  • 并非所有的类Unix平台对[[:alpha:]][[:alnum:]]匹配时,完全支持所有的Unicode字符。例如,使用基于UTF-8的语言环境,OS X 10.9.1显然只匹配拉丁变音符号(例如,ü,á)和西里尔文字符(除ASCII之外),而Linux 3.2似乎涵盖所有脚本,包括亚洲和阿拉伯语。

  • 我不清楚从右到左书写脚本中的名称是否正确匹配。

  • 为了完整起见:即使上述正则表达式不试图强制执行长度的限制,试图与国际化域名这样做会更复杂,因为篇幅所限适用于ASCII编码名称(通过Punycode),而不是原来的。

@Alfe指出IDN问题的提示。

+0

不错的解释是不是这个更小?^@(([a-zA-Z]( - ?[a-zA-Z0-9])*)\。)+ [a-zA-Z] {2,} $ – Arka

+0

@Arka:将允许无效的单字母域名(例如'@ a.com')。请注意,我的正则表达式中的第一个'( - ?[a-zA-Z0-9])'用于_sub_域 - 用'*'量化,而第二个 - 用于_domain_ - 用'+' 。 – mklement0

+0

你是对的,再次感谢。 – Arka

0
echo "@dom.ext" | grep -E "^@[a-zA-Z0-9]+([-.]?[a-zA-Z0-9]+)*.[a-zA-Z]+$" 

该做的工作。

+1

域可以以数字开头? – Alfe

+0

此外,你需要逃避最后一次出现'.'。 – mklement0

1

使用

grep '@[[:alpha:]][[:alnum:]\-]*\.[[:alpha:]][[:alnum:]\-]*\.[[:alpha:]][[:alnum:]\-]*$' 
+0

您假设3个组件(子域),但OP也想匹配域(2个组件)。另外,TLD是否仅由字母组成(.com,.info,...)? – mklement0

+0

是的,没错。但是当进入这样的细节时,我们也可以考虑unicode域(比如www.müller.de),那么[az]也不够,我担心'grep'的'[[:alnum:]]''也可能会错误地处理这些变音(取决于编解码器等)。所以我想我们可以按照你接受的答案来处理它。如果这对于OP是有效的,那应该就足够了。不过,如果他想要有一个明确的答案,我认为我们没有足够的,但是---) – Alfe

+1

好点,谢谢。我已更新了我的帖子,并提供了至少一些答案,并阐明了我的解决方案的局限性。 – mklement0