Адрес IPV6 в сжатой форме на Java

Я использовал метод 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. Аналогично, 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-битных нулевых полей ДОЛЖНА быть сокращена (т. е. последовательность с тремя последовательными нулевыми полями укорачивается в 2001: 0 :0:1:0:0:0:1). Когда длина последовательных 16-битных нулевых полей равна (т. е. 2001:db8:0:0:1:0:0:1), первая последовательность нулевых битов ДОЛЖНА быть укорочена. Например, 2001:db8::1:0:0:1 является правильным представлением.

Я также проверил другой опубликовать в переполнении стека, но не было указано условие (пример выбора в размещении ::).

Есть ли какая-нибудь java-библиотека для этого? Кто-нибудь может мне помочь?

Заранее спасибо.


person Tony    schedule 12.08.2011    source источник


Ответы (7)


Как насчет этого?

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?)

person Tim Pietzcker    schedule 12.08.2011
comment
Это не работает, когда группы имеют начальные нули. Например. 2001:0db8:0:0000:00:000:0002:0000 -> 2001:db8::2:0. Я могу легко исправить это, удалив эти начальные нули, прежде чем использовать ваше регулярное выражение для его сжатия. Но есть ли способ сделать это всего за одно регулярное выражение? - person Victor Stafusa; 04.11.2011
comment
0:0:0:0:5:6:7:8 становится 0::5:6:7:8. Я думаю, что вместо этого должно быть ::5:6:7:8. Так что добавьте .replaceFirst("^0::","::") в конец. - person Mark Rajcok; 09.08.2019

Недавно я столкнулся с той же проблемой и хотел бы (очень немного) улучшить ответ Тима.

Следующее регулярное выражение имеет два преимущества:

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

Во-первых, он включает изменение для соответствия нескольким нулям. Во-вторых, он также правильно сопоставляет адреса, в которых самая длинная цепочка нулей находится в начале адреса (например, 0:0:0:0:0:0:0:1).

person Tim Okrongli    schedule 27.01.2012
comment
Хотя это регулярное выражение работает с адресами типа 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::. - person chrixm; 01.06.2014
comment
Это сжимает 0000:0000:0000:0000:0000:0000:0000:0001 в ::0001 вместо ::1 - person Say No To Censorship; 05.11.2016

java-ipv6 — это почти то, что вам нужно. Начиная с версии 0.10, он не проверяет самый длинный набор нулей для сокращения с помощью :: - например, 0:0:1:: сокращается до ::1:0:0:0:0:0. Однако это очень достойная библиотека для обработки адресов IPv6, и эта проблема должна быть исправлено в версии 0.11, так что библиотека соответствует RFC 5952. соответствует.

person Hans-Peter Störr    schedule 26.03.2013

Класс InetAddresses в Guava имеет toAddrString(), который форматируется в соответствии с RFC 5952.

person David Phillips    schedule 19.06.2017

После выполнения некоторых тестов я думаю, что следующее описывает все различные сценарии IPv6:

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

Java-библиотека IPAddress с открытым исходным кодом может делать то, что описано, она предоставляет множество способов создания строк для 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
person Sean F    schedule 27.03.2018

Не совсем элегантно, но это мое предложение (на основе работы 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;
    }
  1. Результаты:

    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:90 0d: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:94дд:0000:0000:0000:0000 -> 0:0:0:94дд:: 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

person Adrian    schedule 11.10.2019