linux shell正则表达式如何匹配域名(包含中文域名)

linux shell正则表达式如何匹配域名(包含中文)

shell匹配域名


1. 匹配示例

最近的项目需要校验一下域名格式匹配,百度一下,说明如下:

  • DNS规定,域名中的标号都由英文字母和数字组成,每一个标号不超过63个字符,也不区分大小写字母。标号中除连字符(-)外不能使用其他的标点符号。级别最低的域名写在最左边,而级别最高的域名写在最右边。由多个标号组成的完整域名总共不超过255个字符。
    由此匹配完整域名的正则表达式:
^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$

使用例如:

#echo "baidu.com " | egrep "^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$"
#baidu.com

另外搜索到好多这种类似规则:

 ^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$

这类规则使用上面的egrep 会不生效,无法正确匹配,可使用下面的方法:

#echo "baidu.com " | grep -P "^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$"
#baidu.com

2.使用差别

可以从上面的使用上看到,我将 egrep替换成了 grep -P ,原因如下:
A. grep -P

man grep的时候有一个-P,文档上的英文:

-P, --perl-regexp

  Interpret PATTERN as a Perl regular expression.  This is highly experimental and grep -P may warn of  nimplemented features.

这意思是,-P 可以让grep使用perl的正则表达式语法,因为perl的正则更加多元化,能实现更加复杂的场景。

B. egrep

正则表达式根据元字符的数量及功能不同又分为基本正则表达式(grep)和拓展正则表达式(egrep)。而grep和egrep同属于文本搜索工具,可根据用户指定的文本模式(搜索条件)对目标文件进行逐行搜索,显示能匹配到的行。用法上grep –E等同于egrep,与grep和egrep相似的文本搜索工具还有fgrep,因不支持使用正则表达式,所以不再单独介绍。

从上面的区分介绍可知,在使用正则表达上的匹配上,grep -P 的语法更管饭一些,以后使用可多参考perl语法

3.中文域名

上面的匹配和搜索已经可以做到对域名的匹配,但上面的域名匹配中并不包含对中文的匹配。

中文国际域名: 中文域名必须包含汉字,并可以含字母(A-Z,a-z,大小写等价)、数字(0-9)或连接符(-)。各级中文域名之间用实点(.)连接,各级中文域名长度不得超过20个字符。简繁体为不同的域名。

需要将上面的内容和无中文域名结合:
这是我在网上找到的最详细的说明了。对应的正则表达式(不够详细,以下为例):

^[a-zA-Z0-9\u4e00-\u9fa5][-a-zA-Z0-9\u4e00-\u9fa5]{0,62}(\.[a-zA-Z0-9\u4e00-\u9fa5][-a-zA-Z0-9\u4e00-\u9fa5]{0,62})*$

其中,\u4E00-\u9FA5 就是代表着中文的意思,以上的格式在网上的在线正则表达式匹配上都可以执行通过,但是,可但是,拿到linux操作系统中,执行以下脚本,却会报错:

# echo "阿斯蒂芬.dsaf"|egrep "/^[A-Za-z0-9_\u4E00-\u9FA5]+([\.\-][A-Za-z0-9_\u4E00-\u9FA5]+)*$/"
# grep: Invalid range end

搜索了下,没有得到确切的答案,比较靠谱的一个答案这样说:

需要根据系统bash的中文编码规则进行匹配

凉了。这怎么办?

4.为什么[\u4e00-\u9fa5]不能匹配中文(想直接获取匹配包含中文域名的小伙伴,点这里直接跳转

grep正则匹配中文可以考虑:
grep ‘[^\u4e00-\u9fa5]’ test.log (如果不生效,见下面的命令)
注: grep ‘[\u4e00-\u9fa5]’ test.log 命令经常不生效
此外下面命令可生效:
grep -P ‘[\p{Han}]’ test.log
参考:https://blog.csdn.net/u010627840/article/details/41863395

直到找到了上面的说法,才找到匹配的方式,废话不说,上代码:

# echo "2a阿萨德2.sdf.as打扫房间dfas" |grep -P "^(?=^.{3,255}$)[a-zA-Z0-9\p{Han}][-a-zA-Z0-9\p{Han}]{0,62}(\.[a-zA-Z0-9\p{Han}][-a-zA-Z0-9\p{Han}]{0,62})+$"
# 2a阿萨德2.sdf.as打扫房间dfas

成功匹配!!!!!!

5.分析正则表达式

  • (?=^.{3,255}$)
    匹配3-255个字符
  • [a-zA-Z0-9\p{Han}][-a-zA-Z0-9\p{Han}]{0,62}
    匹配“a-z A-Z 0-9 中文 - a-z A-Z 0-9 中文” 以内的的字符,字符个数在0-62之间
  • (.[a-zA-Z0-9\p{Han}][-a-zA-Z0-9\p{Han}]{0,62})+$
    至少出现一次

不知道上面的说法是否正确,如果有不确定的描述,可留言纠正哈~~[\抱拳]

上一篇:刷题-力扣-62


下一篇:LeetCode刷题进阶之圆圈中最后剩下的数字(剑指Offer 62)