IPV6地址在Java中压缩成形式

Ton*_*ony 14 java regex ipv6 regex-negation

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

1)尽可能缩短:例如,2001:db8:0:0:0:0:2:1必须缩短为
2001:db8 :: 2:1.Likewise,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:1:0:0:1),必须缩短第一个零位序列.例如,2001:db8 :: 1:0:0:1是正确的表示.

我还检查了堆栈溢出中的另一个帖子,但没有指定条件(示例选择放置::).

有没有java库来处理这个?有人可以帮帮我吗?

提前致谢.

Tim*_*ker 20

这个怎么样?

String resultString = subjectString.replaceAll("((?::0\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)", "::$2");
Run Code Online (Sandbox Code Playgroud)

没有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.
Run Code Online (Sandbox Code Playgroud)

输入:

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
Run Code Online (Sandbox Code Playgroud)

输出:

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::
Run Code Online (Sandbox Code Playgroud)

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

  • 当组具有前导零时,这不起作用。例如 2001:0db8:0:0000:00:000:0002:0000 -> 2001:db8::2:0。我可以通过在使用正则表达式压缩之前消除这些前导零来轻松解决这个问题。但是有一种方法可以在一个正则表达式中做到这一点吗? (2认同)

小智 8

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

以下正则表达式提供两个优点:

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

首先,它结合了更改以匹配多个零.其次,它还正确地匹配最长的零链在地址开头的地址(例如0:0:0:0:0:0:0:1).