2011-08-12 39 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"