在 Java 中将 IPV6 地址转换为压缩形式

2022-09-02 23:48:22

我已经使用了压缩IPv6地址的方法,输出是,但我需要。,基本上压缩输出应该基于RFC 5952标准,即Inet6Address.getByName("2001:db8:0:0:0:0:2:1").toString()2001:db8:0:0:0:0:2:12001:db8::2:1

  1. 尽可能缩短:例如,2001:db8:0:0:0:0:2:1 必须缩短为
    2001:db8::2:1。同样,2001:db8::0:1 是不可接受的,因为符号 “::” 可用于生成更短的表示形式 2001:db8::1。

  2. 处理一个 16 位 0 字段:符号“::”不得仅用于缩短一个 16 位 0 字段。例如,表示形式 2001:db8:0:1:1:1:1:1 是正确的,但 2001:db8::1:1:1:1:1 是不正确的。

  3. “::” 位置中的选项 = 当放置 “::” 时,必须缩短连续 16 位 0 字段的最长运行时间(即,具有三个连续零字段的序列在 2001 年缩短:0:0:1:0:0:0:1)。当连续的 16 位 0 字段的长度相等时(即 2001:db8:0:0:0:1:0:1),必须缩短第一个零位序列。例如,2001:db8::1:0:0:1 是正确的表示形式。

我还检查了Stack溢出中的另一篇文章,但没有指定条件(放置::)的示例选择。

有没有java库来处理这个问题?任何人都可以帮我吗?

提前致谢。


答案 1

怎么样?

String resultString = subjectString.replaceAll("((?::0\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)", "::$2").replaceFirst("^0::","::");

没有Java双反斜杠地狱的解释:

(       # Match and capture in backreference 1:
 (?:    #  Match this group:
  :0    #  :0
  \b    #  word boundary
 ){2,}  # twice or more
)       # End of capturing group 1
:?      # Match a : if present (not at the end of the address)
(?!     # Now assert that we can't match the following here:
 \S*    #  Any non-space character sequence
 \b     #  word boundary
 \1     #  the previous match
 :0     #  followed by another :0
 \b     #  word boundary
)       # End of lookahead. This ensures that there is not a longer
        # sequence of ":0"s in this address.
(\S*)   # Capture the rest of the address in backreference 2.
        # This is necessary to jump over any sequences of ":0"s
        # that are of the same length as the first one.

输入:

2001:db8:0:0:0:0:2:1
2001:db8:0:1:1:1:1:1
2001:0:0:1:0:0:0:1
2001:db8:0:0:1:0:0:1
2001:db8:0:0:1:0:0:0

输出:

2001:db8::2:1
2001:db8:0:1:1:1:1:1
2001:0:0:1::1
2001:db8::1:0:0:1
2001:db8:0:0:1::

(我希望最后一个例子是正确的 - 或者如果地址以结尾,是否有其他规则?0


答案 2

我最近遇到了同样的问题,并希望(非常轻微地)改进Tim的答案。

以下正则表达式具有两个优点:

((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)

首先,它包含匹配多个零的更改。其次,它还正确匹配地址开头最长零链的地址(例如 )。0:0:0:0:0:0:0:1