用于匹配 IP 版本 6 地址的压缩文本表示的 LEX 模式

LEX Pattern for matching compressed textual representation of an IP version 6 address

我知道在堆栈溢出和正则表达式的其他地方有很多 post,包括 IPV6 地址的 LEX 模式。 None 其中似乎是真正完整的,确实有些要求不需要解析所有可能的地址格式。

我正在寻找 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 的表示集(强调已添加):

…[A]ll implementations MUST accept and be able to handle any legitimate RFC4291 format.

由于正则表达式主要用于识别和解析输入,因此似乎没有必要费心编写和验证可能的规范模式列表。

符合 RFC 4291 §2.2 第 1 条的 IPv6 地址可以很容易地用 lex 语法描述:

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 地址的各种形式,但如果需要,应该清楚如何添加这些地址。