2011-08-12 33 views
13

我用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 standard,即将IPV6地址压缩成Java压缩格式

1)Shorten as Much as Possible:例如,2001:DB8:0:0:0:0:2:1必须被缩短为
2001:DB8 :: 2 :1.同样,2001:db8 :: 0:1是不可接受的, ,因为可以使用符号“::”来产生更短的表示2001:db8 :: 1。

2)Handling One 16-Bit 0 Field:符号 “::” 绝不能使用,以缩短仅一个16位的0场。 例如,表示法2001:db8:0:1:1:1:1:1是正确的,但是不正确。

3)Choice in Placement of "::" : =当在的“::”,连续的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是正确的 表示。

我也检查了another post in Stack overflow,但没有指定条件(示例选择放置::)。

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

在此先感谢。

回答

18

这个怎么样?

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

说明不带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结束)

+0

愿望哪些格式,我可以更不仅仅是+1详细解释 –

+0

+1相当不俗 –

+0

@Tim真棒....非常感谢你的出色答案。 – Tony

9

我最近遇到了同样的问题,想添的回答(非常轻微)提高?

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

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

首先,它结合了变化匹配多个零。其次,它也正确地匹配最长的零链在地址的开始处的地址(例如0:0:0:0:0:0:0:1)。

+0

尽管这个正则表达式处理诸如“0:0:0:0:0:0:0:0”之类的地址,并将其正确地缩短为“::”,但它不再匹配最长的零组(即,它不正确地缩短将“0:0:1:0:0:0:0:0”改为“:: 1:0:0:0:0:0”而不是“0:0:1 ::” – chrixm

+0

这会压缩“0000 :0000:0000:0000:0000:0000:0000:0001'到':: 0001'而不是':: 1' –

1

java-ipv6几乎是你想要的。从版本0.10开始,它不会检查使用::来缩短零的最长时间,例如0:0:1 ::被缩短为:: 1:0:0:0:0:0。尽管如此,它是处理IPv6地址的非常好的库,并且此问题应该是fixed with version 0.11,因此库是RFC 5952 compliant

0

进行一些测试后,我认为下面捕获所有不同的IPv6情景:

"((?:(?::0|0:0?)\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)" -> "::$2"