我知道堆栈溢出和正则表达式的其他地方都有很多文章,包括IPV6地址的LEX模式。它们似乎都不是真正完整的,实际上某些要求不需要解析所有可能的地址格式。
我正在寻找IP版本6地址的LEX模式,仅适用于以压缩文本形式表示的地址。这种形式在RFC 5952的2.2节中(以及可能在其他相关的RFC中)进行了描述,并且表示所有可能的IPv6地址格式的较小子集。
[如果有人拥有经过良好测试或知道的一个,请转发。
RFC 5952 §2.2没有正式描述压缩的IPv6地址形式。 RFC 5952的目标是产生“规范的文本表示形式”。也就是说,一组文本编码与该IPv6地址具有一对一的关系。 2.2节列举了压缩形式的几个方面,这些方面导致了编码选项;规范表示需要消除所有选项。
压缩的语法实际上在RFC 4291 §2.2的第2节中进行了描述。尽管有点烦人,但该语法很容易描述为正则表达式。在包含两个正则表达式的交集的语法中,这样做会更容易(例如,Ragel提供了该运算符),但是在这种情况下,简单地对可能性进行枚举就足够了。
如果您确实想将匹配项限制为RFC 5952 §4.2中列出的规范表示形式,那么您的任务就有些艰巨,因为要求压缩后的0必须是未压缩地址中最长的0,因此,如果有多个相同长度的最长行程,则为第一个此类行程。
这可能通过对压缩行程满足“第一最长”约束条件的允许形式进行更长的枚举。但是我真的不确定创建该怪物是否有任何价值,因为RFC 5952十分清楚,其目的是通过一个合格的应用程序(加强调)来限制表示集[[produced:] accept…[A] ll的实现必须
可以在lex语法中轻松描述符合RFC 4291 §2.2条款1的IPv6地址:
piece [[:xdigit:]]{1,4}
%%
{piece}(:{piece}){7} { /* an uncompressed IPv6 address */ }
顺便说一句,尽管出于上述相同的原因似乎没有必要,但将{piece}
限制为规范的16位表示形式(仅小写,没有前导零)非常简单:
piece 0|[1-9a-f][0-9a-f]{0,3}
复杂性来自第2节的要求,即只压缩一次0。编写正则表达式很容易,它只允许省略一个数字:
(({piece}:)*{piece})?::({piece}(:{piece})*)?
但是该公式不再将片段数限制为8。编写正则表达式也很容易,该表达式允许省略片段,从而限制了字段数:
{piece}(:{piece}?){1,6}:{piece}|:(:{piece}){1,7}|({piece}:){1,7}:|::
需要的是这两种模式的交集,再加上未压缩地址的模式。但是,如上所述,无法在(f)lex中编写交集。因此,我们最终列举了可能性。一个简单的枚举是初始未压缩的片段数:
(?x: /* Flex's extended syntax allows whitespace and continuation lines */
{piece}(:{piece}){7}
| {piece} ::{piece}(:{piece}){0,5}
| {piece}:{piece} ::{piece}(:{piece}){0,4}
| {piece}(:{piece}){2}::{piece}(:{piece}){0,3}
| {piece}(:{piece}){3}::{piece}(:{piece}){0,2}
| {piece}(:{piece}){4}::{piece}(:{piece})?
| {piece}(:{piece}){5}::{piece}
| {piece}(:{piece}){0,6}::
| ::{piece}(:{piece}){0,6}
| ::
)
这仍然排除了在IPv6中嵌入IPv4地址的各种形式,但是如果需要,应该清楚如何添加这些形式。