我正在尝试为只匹配有效域的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 :(得分:8)
真正完整的解决方案需要更多工作 ,但这里的 近似可能效果不错(注意假设@
前缀,并且输入字符串应该以它开头):
^@(([a-zA-Z](-?[a-zA-Z0-9])*)\.)+[a-zA-Z]{2,}$
您可以将其与egrep
(或grep -E
)一起使用,也可以与[[ ... =~ ... ]]
bash的正则表达式匹配运算符一起使用。
做出以下假设,这些假设比实际DNS名称约束更宽松:
只允许使用ASCII(非外国)字母 - 请参阅下面的国际化域名(IDN)注意事项;此外,Punycode *(ASCII兼容)形式的IDN - 例如,xn--bcher-kva.ch
用于bücher.ch
- 不匹配 - 见下文。
嵌套子域的数量没有限制。
对任何标签(名称组件)的长度没有限制,并且对名称的总长度没有限制(对于实际限制,请参阅here)。
TLD(最后一个组成部分)仅由字母组成,长度至少为2.
子域名和域名都必须以字母开头;子域名允许为单字母。
这是一个快速测试:
for d in @subdom..dom.ext @dom.ext @subdom.dom.ext @subsubdom.subdom.dom.ext @subsub-dom.sub-dom.ext @x.org; do
[[ $d =~ \
^@(([a-zA-Z](-?[a-zA-Z0-9])*)\.)+[a-zA-Z]{2,}$ \
]] && echo YES || echo NO
done
使用文字 Unicode字符支持Internationalized Domain Names (IDN) - 再次,完整的解决方案需要更多工作:
与IDN匹配的简单改进是将[a-zA-Z]
替换为[[:alpha:]]
,将[a-zA-Z0-9]
替换为上述正则表达式中的[[:alnum:]]
;即:
^@(([[:alpha:]](-?[[:alnum:]])*)\.)+[[:alpha:]]{2,}$
警告:
没有尝试识别Punycode - 编码的IDN版本,它们使用前缀为{{1}的基于ASCII的编码然后需要解码。
正如Patrick Mevzek所指出的,上述可以产生误报和误报(使用他的示例):
xn--
ab--whatever
,它使用法语域名中的希腊字母 - 这是一个单凭正则表达式无法执行的规则。cαfe.fr
(.ws
)xn--jr8h.ws
今天是IANA根目录中的有效顶级域名,但与பரிட்சை
不匹配与[[:alpha:]]{2,}$
或[[:alpha:]]
匹配时,并非所有类Unix平台都完全支持所有Unicode字母。例如,使用基于UTF-8的语言环境,OS X 10.9.1显然只匹配拉丁语变音符号(例如[[:alnum:]]
,ü
)和西里尔字符(除ASCII之外),而Linux 3.2值得称赞似乎涵盖了所有脚本,包括亚洲和阿拉伯语脚本。
我不清楚从右到左书写脚本中的名称是否正确匹配。
为了完整起见:即使上面的正则表达式没有尝试强制执行长度限制,尝试使用IDN这样做也会复杂得多,因为长度限制适用于 ASCII 名称的编码(通过Punycode),而不是原始的。
对@Alfe的提示和指出IDN问题的提示,以及@Arka提供正则表达式的简化版本以替换我最初在错误的假设下制作的较长版本 - 必须排除字母域名。
答案 1 :(得分:1)
使用
grep '@[[:alpha:]][[:alnum:]\-]*\.[[:alpha:]][[:alnum:]\-]*\.[[:alpha:]][[:alnum:]\-]*$'
答案 2 :(得分:0)
echo "@dom.ext" | grep -E "^@[a-zA-Z0-9]+([-.]?[a-zA-Z0-9]+)*.[a-zA-Z]+$"
这完成了这项工作。