Регулярное выражение, которое соответствует всем допустимым адресам IPv6 формата

На первый взгляд, я признаю, что этот вопрос выглядит как дубликат этого вопроса и любые другие связанные с ним:

Регулярное выражение, которое соответствует допустимым адресам IPv6

У этого вопроса есть ответ, который почти отвечает на мой вопрос: , но не полностью.

Код из этого вопроса, с которым у меня возникают проблемы, но с наибольшим успехом, показан ниже:

private string RemoveIPv6(string sInput)
{
    string pattern = @"(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
    //That is one looooong regex! From: /info/19824/regular-expression-that-matches-valid-ipv6-addresses/147535#147535
    //if (IsCompressedIPv6(sInput))
      //  sInput = UncompressIPv6(sInput);
    string output = Regex.Replace(sInput, pattern, "");
    if (output.Contains("Addresses"))
        output = output.Substring(0, "Addresses: ".Length);

    return output;
}

Проблемы, которые у меня были с шаблоном регулярного выражения, как указано в этом ответе, David M. Syzdek Answer, заключается в том, что он не 't сопоставить и удалить полную форму адресов IPv6, которые я бросаю на нее.

Я использую шаблон регулярного выражения, чтобы в основном заменять адреса IPv6 в строках пробелами или нулевым значением.

Например,

    Addresses:  2404:6800:4003:c02::8a

Также как...

    Addresses:  2404:6800:4003:804::200e

И наконец...

    Addresses:  2001:4998:c:a06::2:4008

Все либо не полностью совпадают с регулярным выражением, либо не могут быть полностью сопоставлены.

Регулярное выражение вернет мне остальные части строки, как показано ниже:

    Addresses:  8a

    Addresses:  200e

    Addresses:  2:4008

Как можно видеть, он оставил остатки адресов IPv6, которые трудно обнаружить и удалить из-за различных форматов, которые сохраняют остатки. Ниже приведен шаблон регулярного выражения для лучшего анализа:

(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))

Следовательно, мой вопрос, как этот шаблон регулярного выражения можно скорректировать, чтобы он мог соответствовать и, следовательно, разрешить полное удаление любых адресов IPv6, из строки, которая не содержит только IPv6 адрес себя?

Альтернативно, как можно скорректировать приведенный выше фрагмент кода выше, чтобы обеспечить требуемый результат?

Для тех, кому может быть интересно, я получаю строку из команд StandardOutput nslookup, а адреса IPv6 всегда будут отличаться. Для приведенных выше примеров я получил эти адреса IPv6 с "google.com" и "yahoo.com".

Я не использую встроенную функцию для разрешения записей DNS по уважительной причине, которая, на мой взгляд, не имеет значения на данный момент, поэтому я использую nslookup.

Что касается кода, который вызывает эту функцию, если требуется, является следующим: (Он сам также является другой функцией/методом или, скорее, частью одного)

string output = "";
string garbagecan = "";
string tempRead = "";
string lastRead = "";
using (StreamReader reader = nslookup.StandardOutput)
{
     while (reader.Peek() != -1)
     {
         if (LinesRead > 3)
         {
             tempRead = reader.ReadLine();
             tempRead = RemoveIPv6(tempRead);

             if (tempRead.Contains("Addresses"))
                 output += tempRead;
             else if (lastRead.Contains("Addresses"))
                 output += tempRead.Trim() + Environment.NewLine;
             else
                 output += tempRead + Environment.NewLine;
             lastRead = tempRead;
         }
         else
             garbagecan = reader.ReadLine();
         LinesRead++;
     }
 }
 return output;

Исправленное регулярное выражение должно разрешать удаление адресов IPv6 и оставить IPv4-адреса нетронутыми. Строка, которая будет передана в регулярное выражение, не будет содержать только адреса IPv6, и почти всегда будет содержать другие данные, и, как таковая, непредсказуемо, по каким индексам будут отображаться адреса. Регулярное выражение также пропускает все другие адреса IPv6 после первых адресов IPv6 по какой-либо причине, следует отметить.

Извините, если есть какие-то недостающие детали, я постараюсь изо всех сил включить их в случае предупреждения. Я также предпочел бы, если это возможно, образцы кода работы, поскольку у меня почти нулевое знание относительно регулярного выражения.

Ответ 1

(?:^|(?<=\s))(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))(?=\s|$)

Используя lookarounds, вы можете обеспечить полное совпадение, а не partial match.See demo.

https://regex101.com/r/cT0hV4/5