IPv6アドレスをより妥当な正規表現でマッチする。

と言うサイトがあります。IPv6アドレスとして妥当かチェックしてくれる上に、RFC5952に則った表記を教えてくれます。


ここでは正規表現によってIPv6アドレスとして正しいか評価しています。
それは、以下のような正規表現です。

  • IPv6アドレスをマッチする。
    • 圧縮済みIPv6アドレスでもマッチする
    • IPv4アドレスが含まれていてもマッチする
    • リンクローカルアドレスを識別する為のインターフェース名が含まれていてもマッチする
((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$

何か凄い量ですね。以下、理解し易くする為にフォーマットしてみました。

(
  (
    ([0-9a-f]{1,4}:){7}
    ([0-9a-f]{1,4}
    |:)
  )|
  (
    ([0-9a-f]{1,4}:){6}
    (:[0-9a-f]{1,4}|
      ((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})
    |:)
  )|
  (
    ([0-9a-f]{1,4}:){5}(
      ((:[0-9a-f]{1,4}){1,2})|:
      ((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})
    |:)
  )|
  (
    ([0-9a-f]{1,4}:){4}(
      ((:[0-9a-f]{1,4}){1,3})|
      ((:[0-9a-f]{1,4})?:
        ((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})
      )
    |:)
  )|
  (
    ([0-9a-f]{1,4}:){3}(
      ((:[0-9a-f]{1,4}){1,4})|
      ((:[0-9a-f]{1,4}){0,2}:
        ((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})
      )
    |:)
  )|
  (
    ([0-9a-f]{1,4}:){2}(
      ((:[0-9a-f]{1,4}){1,5})|
      ((:[0-9a-f]{1,4}){0,3}:
        ((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})
      )
    |:)
  )|
  (
    ([0-9a-f]{1,4}:){1}(
      ((:[0-9a-f]{1,4}){1,6})|
      ((:[0-9a-f]{1,4}){0,4}:
        ((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})
      )
    |:)
  )|
  (:
    (
      ((:[0-9a-f]{1,4}){1,7})|
      ((:[0-9a-f]{1,4}){0,5}:
        ((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})
      )
    |:)
  )
)(%.+)?\s*$

こうしてみると、相応に冗長な表現になってしまっているものの、
正規表現の理解が難しい機能や、複雑な表現は全く使っていない事が分かります。