我使用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,即
1)Shorten as Much as Possible:例如,2001:db8:0:0:0:0:2:1必须缩短为
2001:db8 :: 2:1.Likewise,2001:db8 :: 0:1是不可接受的,
因为符号“::”本来可以用来产生一个
较短的表示形式2001:db8 :: 1。
2) Handling One 16-Bit 0 Field :符号“::”不得用于缩短一个16位0字段。 例如,表示形式2001:db8:0:1:1:1:1:1是正确的,但是 2001:db8 :: 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库来处理这个问题?有人可以帮帮我吗?
提前致谢。
答案 0 :(得分:19)
这个怎么样?
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
结尾,还是有其他规则吗?)
答案 1 :(得分:9)
我最近遇到了同样的问题,并希望(非常轻微地)改进Tim的答案。
以下正则表达式有两个优点:
((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)
首先,它结合了更改以匹配多个零。其次,它还正确地匹配最长的零链在地址开头的地址(例如0:0:0:0:0:0:0:1
)。
答案 2 :(得分:2)
java-ipv6几乎就是你想要的。从版本0.10开始,它不检查用:: - 例如0:0:1 ::缩短为:: 1:0:0:0:0:0时缩短的最长零。但是,它是一个非常不错的处理IPv6地址的库,这个问题应该是fixed with version 0.11,这样库就是RFC 5952 compliant。
答案 3 :(得分:1)
Guava的InetAddresses
类具有toAddrString(),其格式符合RFC 5952。
答案 4 :(得分:0)
执行一些测试后,我认为以下内容捕获了所有不同的IPv6场景:
"((?:(?::0|0:0?)\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)" -> "::$2"
答案 5 :(得分:0)
The open-source IPAddress Java library可以按照描述进行操作,它提供了多种为IPv4和/或IPv6生成字符串的方法,包括用于IPv6的规范字符串与rfc 5952匹配。免责声明:我是该库的项目经理。
使用您列出的示例,示例代码为:
IPAddress addr = new IPAddressString("2001:db8:0:0:0:0:2:1").getAddress();
System.out.println(addr.toCanonicalString());
// 2001:db8::2:1
addr = new IPAddressString("2001:db8:0:1:1:1:1:1").getAddress();
System.out.println(addr.toCanonicalString());
// 2001:db8:0:1:1:1:1:1
addr = new IPAddressString("2001:0:0:1:0:0:0:1").getAddress();
System.out.println(addr.toCanonicalString());
// 2001:0:0:1::1
addr = new IPAddressString("2001:db8:0:0:1:0:0:1").getAddress();
System.out.println(addr.toCanonicalString());
//2001:db8::1:0:0:1
答案 6 :(得分:0)
不太优雅,但这是我的建议(基于 chrixm 的工作):
public static String shortIpv6Form(String fullIP) {
fullIP = fullIP.replaceAll("^0{1,3}", "");
fullIP = fullIP.replaceAll("(:0{1,3})", ":");
fullIP = fullIP.replaceAll("(0{4}:)", "0:");
//now we have full form without unnecessaires zeros
//Ex:
//0000:1200:0000:0000:0000:0000:0000:0000 -> 0:1200:0:0:0:0:0:0
//0000:0000:0000:1200:0000:0000:0000:8351 -> 0:0:0:1200:0:0:0:8351
//0000:125f:0000:94dd:e53f:0000:61a9:0000 -> 0:125f:0:94dd:e53f:0:61a9:0
//0000:005f:0000:94dd:0000:cfe7:0000:8351 -> 0:5f:0:94dd:0:cfe7:0:8351
//compress to short notation
fullIP = fullIP.replaceAll("((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)", "::$2");
return fullIP;
}
结果:
7469:125f:8eb6:94dd:e53f:cfe7:61a9:8351-> 7469:125f:8eb6:94dd:e53f:cfe7:61a9:8351 7469:125f:0000:0000:e53f:cfe7:0000:0000-> 7469:125f :: e53f:cfe7:0:0 7469:125f:0000:0000:000f:c000:0000:0000-> 7469:125f :: f:c000:0:0 7469:125f:0000:0000:000f:c000:0000:0000-> 7469:125f :: f:c000:0:0 7469:0000:0000:94dd:0000:0000:0000:8351-> 7469:0:0:94dd :: 8351 0469:125f:8eb6:94dd:0000:cfe7:61a9:8351-> 469:125f:8eb6:94dd:0:cfe7:61a9:8351 0069:125f:8eb6:94dd:0000:cfe7:61a9:8351-> 69:125f:8eb6:94dd:0:cfe7:61a9:8351 0009:125f:8eb6:94dd:0000:cfe7:61a9:8351-> 9:125f:8eb6:94dd:0:cfe7:61a9:8351 0000:0000:8eb6:94dd:e53f:0007:6009:8350-> :: 8eb6:94dd:e53f:7:6009:8350 0000:0000:8eb6:94dd:e53f:0007:6009:8300 -> :: 8eb6:94dd:e53f:7:6009:8300 0000:0000:8eb6:94dd:e53f:0007:6009:8000-> :: 8eb6:94dd:e53f:7:6009:8000 7469:0000:0000:0000:e53f:0000:0000:8300 -> 7469 :: e53f:0:0:8300 7009:100f:8eb6:94dd:e000:cfe7:6009:8351-> 7009:100f:8eb6:94dd:e000:cfe7:6009:8351 7469:100f:8006:900d:e53f:cfe7:61a9:8351-> 7469:100f:8006:900d:e53f:cfe7:61a9:8351 7000:1200:8e00:94dd:e53f:cfe7:0000:0001-> 7000:1200:8e00:94dd:e53f:cfe7:0:1 0000:0000:0000:0000:0000:0000:0000:0000-> :: 0000:0000:0000:94dd:0000:0000:0000:0000-> 0:0:0:94dd :: 0000:1200:0000:0000:0000:0000:0000:0000-> 0:1200 :: 0000:0000:0000:1200:0000:0000:0000:8351-> :: 1200:0:0:0:8351 0000:125f:0000:94dd:e53f:0000:61a9:0000-> 0:125f:0:94dd:e53f:0:61a9:0 7469:0000:8eb6:0000:e53f:0000:61a9:0000 -> 7469:0:8eb6:0:e53f:0:61a9:0 0000:125f:0000:94dd:0000:cfe7:0000:8351-> 0:125f:0:94dd:0:cfe7:0:8351 0000:025f:0000:94dd:0000:cfe7:0000:8351 -> 0:25f:0:94dd:0:cfe7:0:8351 0000:005f:0000:94dd:0000:cfe7:0000:8351-> 0:5f:0:94dd:0:cfe7:0:8351 0000:000f:0000:94dd:0000:cfe7:0000:8351-> 0:f:0:94dd:0:cfe7:0:8351 0000:0000:0000:0000:0000:0000:0000:0001-> :: 1