用正则表达式匹配IPv6地址

先看一下IPv6地址格式:
没有压缩的时候,是8组16进制数(0-9a-fA-F),每组4个:


2001:0000:1F1F :0000:0000:0100:11A0:ADDF


为了简化其表示法, rfc2373提出每段中前面的0可以省略:


2001:0:1F1F :0:0:100:11A0:ADDF


连续的0可省略为"::",但只能出现一次。


2001:0:1F1F ::100:11A0:ADDF



没有压缩时,正则表达式:
首先构造出8组中的一组,每个十六进制重复4次:


[0-9A-Fa-f]{4}


由于每组中间用冒号隔开,所以需要第一组和后面7个以冒号开头的组。这样就构造出了一个完整的格式


[0-9A-Fa-f]{4}(:[0-9A-Fa-f]{4}){7}



省略每段中前面的0时:
基本上和之前的一样,只是每组的长度是变化的,每组长度1-4个。
首先构造出8组中的一组,每个十六进制重复1~4次:


[0-9A-Fa-f]{1,4}


完整的格式:


[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){7}


这个格式包含了上面的那种情况。


将连续的0用双冒号压缩时:
这种情况就比较复杂,因为如果不知道双冒号究竟压缩了几个组,也就不知道每个组重复几次。
但是当我知道冒号之前有几个组时,后面就能确定重复几个组了。
第一种情况,当双冒号出现在最开始时,最少压缩2个组,最多压缩7个组。那么双冒号后面可以有1到6组。


:(:[0-9A-Fa-f]{1,4}){1,6}


第二种情况,当双冒号出现在最后时,最少压缩2个组,最多压缩7个组。那么双冒号前面面可以有1到6组。


([0-9A-Fa-f]{1,4}:){1,6}:


第三种情况,当双冒号出现在第1组之后时,最少压缩1个组,最多压缩6个组。那么双冒号后面可以有1到6组。


([0-9A-Fa-f]{1,4}):(:[0-9A-Fa-f]{1,4}){1,6}


第四种情况,当双冒号出现在第2组之后时,最少压缩1个组,最多压缩5个组。那么双冒号后面可以有1到5组。


([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5}


之后几种情况以此类推:


([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4}
([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3}
([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2}
([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4})


最后,当出现全部是0时:


::


总结,当出现压缩时,全部情况:


(:[0-9A-Fa-f]{1,4}){1,6}
([0-9A-Fa-f]{1,4}:){1,6}:
([0-9A-Fa-f]{1,4}):(:[0-9A-Fa-f]{1,4}){1,6}
([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5}
([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4}
([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3}
([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2}
([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4})
::


不压缩时:


[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){7}



现在所有的情况都已经包含在内,我们用分支把他们连起来:


([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){7})|(:(:[0-9A-Fa-f]{1,4}){1,6})|(([0-9A-Fa-f]{1,4}:){1,6}:)|(([0-9A-Fa-f]{1,4}):(:[0-9A-Fa-f]{1,4}){1,6})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3})|(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2})|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}))|(::)



测试一下:


ip addr show |grep -E '([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){7})|(:(:[0-9A-Fa-f]{1,4}){1,6})|(([0-9A-Fa-f]{1,4}:){1,6}:)|(([0-9A-Fa-f]{1,4}):(:[0-9A-Fa-f]{1,4}){1,6})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3})|(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2})|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}))|(::)'

    inet6 ::1/128 scope host
    inet6 2607:8700:101:72d9::88/128 scope global
    inet6 2607:8700:101:72d9::/128 scope global
 
 


 
正则表达式可视话工具:
https://jex.im/regulex/

0 个评论

要回复文章请先登录注册