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

У меня проблемы с написанием регулярного выражения, которое соответствует действительным адресам IPv6, в том числе в их сжатой форме (с :: или ведущими нулями, опущенными в каждой паре байтов).

Может ли кто-нибудь предложить регулярное выражение, которое удовлетворяет требованию?

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


person readonly    schedule 10.09.2008    source источник
comment
Ознакомьтесь с intermapper.com/ipv6validator .. он ссылается на этот сценарий тестирования perl   -  person Mottie    schedule 26.01.2013
comment
Я пробовал все ответы ниже, и они не работают для всех моих тестовых случаев и / или они также включают IPv4, о котором не просили. Я обнаружил, что это самое чистое решение: stackoverflow.com/a/21944928/3112803   -  person gfrobenius    schedule 22.02.2014


Ответы (30)


Мне не удалось получить ответ @Factor Mystic для работы с регулярными выражениями POSIX, поэтому я написал тот, который работает с регулярными выражениями POSIX и регулярными выражениями PERL.

Он должен соответствовать:

Регулярное выражение 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 RegEx
(
([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|          # 1:2:3:4:5:6:7:8
([0-9a-fA-F]{1,4}:){1,7}:|                         # 1::                              1:2:3:4:5:6:7::
([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|         # 1::8             1:2:3:4:5:6::8  1:2:3:4:5:6::8
([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|  # 1::7:8           1:2:3:4:5::7:8  1:2:3:4:5::8
([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|  # 1::6:7:8         1:2:3:4::6:7:8  1:2:3:4::8
([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|  # 1::5:6:7:8       1:2:3::5:6:7:8  1:2:3::8
([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|  # 1::4:5:6:7:8     1:2::4:5:6:7:8  1:2::8
[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|       # 1::3:4:5:6:7:8   1::3:4:5:6:7:8  1::8  
:((:[0-9a-fA-F]{1,4}){1,7}|:)|                     # ::2:3:4:5:6:7:8  ::2:3:4:5:6:7:8 ::8       ::     
fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|     # fe80::7:8%eth0   fe80::7:8%1     (link-local IPv6 addresses with zone index)
::(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])|          # ::255.255.255.255   ::ffff:255.255.255.255  ::ffff:0:255.255.255.255  (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
([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])           # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
)

# IPv4 RegEx
((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])

Чтобы упростить понимание вышеизложенного, следующий "псевдокод" повторяет приведенное выше:

IPV4SEG  = (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])
IPV4ADDR = (IPV4SEG\.){3,3}IPV4SEG
IPV6SEG  = [0-9a-fA-F]{1,4}
IPV6ADDR = (
           (IPV6SEG:){7,7}IPV6SEG|                # 1:2:3:4:5:6:7:8
           (IPV6SEG:){1,7}:|                      # 1::                                 1:2:3:4:5:6:7::
           (IPV6SEG:){1,6}:IPV6SEG|               # 1::8               1:2:3:4:5:6::8   1:2:3:4:5:6::8
           (IPV6SEG:){1,5}(:IPV6SEG){1,2}|        # 1::7:8             1:2:3:4:5::7:8   1:2:3:4:5::8
           (IPV6SEG:){1,4}(:IPV6SEG){1,3}|        # 1::6:7:8           1:2:3:4::6:7:8   1:2:3:4::8
           (IPV6SEG:){1,3}(:IPV6SEG){1,4}|        # 1::5:6:7:8         1:2:3::5:6:7:8   1:2:3::8
           (IPV6SEG:){1,2}(:IPV6SEG){1,5}|        # 1::4:5:6:7:8       1:2::4:5:6:7:8   1:2::8
           IPV6SEG:((:IPV6SEG){1,6})|             # 1::3:4:5:6:7:8     1::3:4:5:6:7:8   1::8
           :((:IPV6SEG){1,7}|:)|                  # ::2:3:4:5:6:7:8    ::2:3:4:5:6:7:8  ::8       ::       
           fe80:(:IPV6SEG){0,4}%[0-9a-zA-Z]{1,}|  # fe80::7:8%eth0     fe80::7:8%1  (link-local IPv6 addresses with zone index)
           ::(ffff(:0{1,4}){0,1}:){0,1}IPV4ADDR|  # ::255.255.255.255  ::ffff:255.255.255.255  ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
           (IPV6SEG:){1,4}:IPV4ADDR               # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
           )

Я разместил на GitHub скрипт, который проверяет регулярное выражение: https://gist.github.com/syzdek/6086792

person David M. Syzdek    schedule 26.07.2013
comment
Отличный ответ. Я только мог пожелать, чтобы RegexPlanet работал прямо сейчас (почему-то это не позволяет мне сделать ссылку для общего доступа), так как я сделал вариант без захвата и добавил все ваши примеры в качестве теста. - person Rade_303; 24.01.2014
comment
Почему вы используете экранирование перед . в шаблоне ip4, а . неэкранировано в шаблоне ip6? Это намеренно? - person Kuba Wyrostek; 27.02.2014
comment
Регулярное выражение IPv4 не соответствует IP-адресам типа 127.000.000.001 - person Kentzo; 13.03.2014
comment
Сегменты IPv4 не должны включать начальные нули. Если присутствует начальный ноль, сегмент IPv4 следует интерпретировать в восьмеричном формате. Таким образом, приведенный выше IPV4SEG правильно не допускает «000». Однако он разрешает «00», чего не должен. - person par; 26.07.2014
comment
У меня не сработало в браузере, как я ожидал. Проверено даже reg.test ('3zzzzffe: 1900: 4545: 3: 200: f8ff: fe21: 67cf'), который, очевидно, не является действительным IPv6-адресом. Здесь были гораздо лучшие результаты с регулярным выражением: nbviewer.ipython. org / github / rasbt / python_reference / blob / master / - person Capaj; 09.02.2015
comment
Соответствует :: _, который, насколько я могу судить, не является действительным IP-адресом. - person Seth Holladay; 23.03.2015
comment
фантастическое регулярное выражение ipv6. нашел небольшую ошибку с ссылкой локального раздела. у вас было fe80, где должно быть что-то вроде [fF][eE]80 и ffff, которое должно быть что-то вроде [fF]{4} - person user2831628; 25.03.2015
comment
У вас есть ошибка в отображении ipv4, он должен ожидать двойное двоеточие, например (([0-9a-fA-F] {1,4}:) {1,4}:) ([0-9a-fA-F] {1, 4} :) IPv4regex - person teodozjan; 16.06.2015
comment
Для сопоставления IPv4 с ведущими нулями вы можете использовать: (25 [0-5] | 2 [0-4] \ d | [0-1]? \ D? \ D) (\. (25 [0-5] | 2 [0-4] \ d | [0-1]? \ D? \ D)) {3} - person serfer2; 20.08.2015
comment
Вопрос Арии stackoverflow.com/questions/32368008/ содержит ответ на последний комментарий. - person Alexei Levenkov; 03.09.2015
comment
+1 для демонстрации того, что регулярные выражения могут быть (как и любой исходный код) действительно читаемыми, если вы позаботитесь о них и отформатируете их. - person Natix; 15.12.2015
comment
Хотя написание шаблонов регулярных выражений не представляет большого труда, если вы знаете, что ищете, это рутинная задача, подверженная ошибкам. Большое спасибо за то, что нашли время сделать это правильно, а также за то, что разбили его полезными комментариями! - person Marcin Kaminski; 18.02.2016
comment
У меня не работает: $ [[2001: bobbydavro :: 1 = ~ $ RE_IPV6]] && echo yes || эхо нет да - person fileinster; 15.03.2016
comment
Я поместил это в форму Python RE: gist.github.com/dfee/6ed3a4b05cfe7a840840 - person Devin; 26.10.2016
comment
Неудачный тестовый пример: fe80 :: 0202: B3FF: FE1E: 8329 - person pmarreck; 20.10.2017
comment
... (продолжение) ... переместите правило fe80 первым и правило :((:IPV6SEG){1,7} последним, которому предшествует правило ::(ffff (предпоследнее). (IPV6SEG:){7,7}: - третий с последнего. - person ergohack; 07.12.2017
comment
... (продолжение) ... переместите (IPV6SEG:){1,4}:IPV4ADDR правило перед правилом (IPV6SEG:){1,4}(:IPVSEG){1,3}. - person ergohack; 07.12.2017
comment
Наконец, ... на моей платформе по неизвестным причинам мне пришлось изменить IPV4SEG на (25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9]) или более строгий (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]{0,1}[0-9]), чтобы 09 и 08 не интерпретировались как недопустимые восьмеричные числа. - person ergohack; 07.12.2017
comment
Я случайно нашел форму, которая ошибочно передается: 2. 81fa: a3c: 206e: 334e: b77f :: - person Mr.B; 14.02.2018
comment
@ergohack, можете ли вы опубликовать свое рабочее решение Regex для обработки ленивого выхода? - person OwN; 09.08.2018
comment
@OwN, к сожалению, 78 символов слишком длинны и не могут быть опубликованы в качестве альтернативного ответа на этот закрытый тред, ... Я опубликую его в последующих комментариях, пожалуйста, внимательно сшивайте: (fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}: - person ergohack; 10.08.2018
comment
@OwN - часть 2: |([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])\.{3,3})(25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])\.{3,3})(25[0-5]|2[0-4][0-9]|1{0,1}[0-9]{0,1}[0-9])|:((:[0-9a-fA-F]{1,4}){1,7}|:)) - person ergohack; 10.08.2018
comment
Вышеупомянутое регулярное выражение говорит, что этот 1::2::3 IPv6-адрес действителен :) - person Chandra Nakka; 30.10.2019
comment
Все IP-адреса в среднем столбце неверны. Согласно этому ответу, двойное двоеточие может использоваться для замены последовательных блоков нулей, ЕСЛИ длина нулей больше одного блока. - person Marko; 20.12.2019
comment
@ChandraNakka, нет. - person nicolai; 11.05.2020
comment
провалы f102 :: 1 - person Konrads; 27.05.2020
comment
Учтите, что [0-9a-fA-F] неправильно совпадает с некоторыми языковыми стандартами, например турецким ç. Вы должны использовать специальные имена классов символов [[:xdigit:]] и [[:digit:]] или переключить языковой стандарт на POSIX или C перед выполнением такого сопоставления с регулярным выражением. - person Léa Gris; 04.06.2020
comment
Любопытный. Он не соответствует 127.0.0.1, несмотря на присутствие сегмента IPv4 - person JamesTheAwesomeDude; 17.05.2021

Следующее будет проверять адреса IPv4, IPv6 (полные и сжатые) и IPv6v4 (полные и сжатые):

'/^(?>(?>([a-f0-9]{1,4})(?>:(?1)){7}|(?!(?:.*[a-f0-9](?>:|$)){8,})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f0-9]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?4)){3}))$/iD'
person Community    schedule 20.12.2009
comment
Несмотря на то, что проверка IP-адресов может быть выполнена, как предлагает Фрэнк Крюгер, это решение является тем, которое действительно отвечает на вопрос (хотя я еще не полностью его тестировал), а также если у вас много IP-адресов, которые вы хотите синтаксически протестировать. и, возможно, соответствует строке текста, вы не можете использовать метод проверки IP. - person Gyuri; 06.12.2011
comment
Привет, я тестировал этот RegExp и не работал у меня. Он говорит, что D является недопустимым флагом, и когда я его удаляю, он говорит SyntaxError: недопустимый квантификатор - person Diosney; 04.12.2012
comment
Какое программное обеспечение вы используете? Это работает с PCRE, но не с Perl. - person MichaelRushton; 04.12.2012
comment
Интерфейсный javascript. Вот код, который я использовал var pattern = /PATTERN/; return [pattern.test(value), 'The Address entered is invalid.']; - person Diosney; 04.12.2012
comment
JavaScript реализует подмножество регулярных выражений в стиле Perl, а не весь PCRE. Мое регулярное выражение не будет работать без некоторых расширенных функций PCRE. - person MichaelRushton; 04.12.2012
comment
Это дает мне исключение в С # - person sarat; 07.05.2013
comment
Неудачный тестовый пример: FE80: 0000: 0000: 0000: 0202: B3FF: FE1E: 8329 Используется последняя версия Elixir на эту дату, которая использует PCRE ниже. - person pmarreck; 20.10.2017
comment
C # не поддерживает атомарную группировку (например, (?>). - person ergohack; 07.12.2017
comment
Эта форма не работает для всех возможных форм ipv6. - person Mr.B; 14.02.2018

Похоже, вы используете Python. Если это так, вы можете использовать что-то вроде этого:

import socket

def check_ipv6(n):
    try:
        socket.inet_pton(socket.AF_INET6, n)
        return True
    except socket.error:
        return False

print check_ipv6('::1') # True
print check_ipv6('foo') # False
print check_ipv6(5)     # TypeError exception
print check_ipv6(None)  # TypeError exception

Я не думаю, что вам нужно компилировать IPv6 в Python, чтобы получить inet_pton , который также может анализировать адреса IPv4, если вы передадите socket.AF_INET в качестве первого параметра. Примечание: это может не работать в системах, отличных от Unix.

person Joe Hildebrand    schedule 17.09.2008
comment
Вы должны указать тип исключения в предложении except. В противном случае except поймает все и может замаскировать несвязанные ошибки. Тип здесь должен быть socket.error. - person Ayman Hourieh; 20.12.2009
comment
A) inet_pton не генерирует другие исключения, если только документы не ошибочны, и B) даже если это так, что еще вы бы вернули, кроме False? - person Joe Hildebrand; 22.12.2009
comment
Re: другие ошибки ... если пользователь передает не-строку, TypeError съедается. Очевидно, что список не является ipv6, но я, вероятно, хотел бы, чтобы он придирался к тому, что я передал неправильный тип. - person Gregg Lind; 22.04.2010
comment
+1 Это мне очень помогло. Следует добавить пару дополнительных моментов: 1) socket.inet_pton может использоваться для проверки действительности обоих семейств IP-адресов (IP и IPv6). 2) Документы здесь (docs.python.org/2/library/socket.html) предполагают, что это доступно на платформах Unix. Это может быть недоступно на Win-платформах. - person mkoistinen; 05.12.2013
comment
используя django, и это помогает! - person elad silver; 18.05.2015

Из "регулярного выражения IPv6":

(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}\Z)|
(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\Z)|
(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\Z)|
(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\Z)|
(\A([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\Z)|
(\A([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}\Z)|
(\A(([0-9a-f]{1,4}:){1,7}|:):\Z)|
(\A:(:[0-9a-f]{1,4}){1,7}\Z)|
(\A((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)|
(\A(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)|
(\A([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)
person Factor Mystic    schedule 10.09.2008
comment
Подобное регулярное выражение должно быть запахом кода, что, возможно, регулярное выражение здесь не лучшее решение. (Хотя, полагаю, оператор действительно просил об этом ...) - person Thanatos; 18.08.2010
comment
@ user712092 - все, кто видел базу кода с такими бельями на глазу - person danielpops; 12.01.2012
comment
Это совершенно ненужная пародия на RE. Программа, создавшая его, не понимала, что делает. Человек никогда бы так не поступил. Пусть вас не вводит в заблуждение кажущаяся сложность - RE действительно являются черной магией для многих людей, но нет причин размещать их на другой планете! - person Chuck Kollars; 07.09.2015
comment
+1 но O.M.G. должен быть лучший способ сделать это: P Для справки: для Rails это может помочь: stackoverflow.com/questions/16965697/ - person Tilo; 29.07.2016
comment
Это действительно запах кода; однако, посмотрев, вы увидите, что каждое регулярное выражение довольно лаконично. Проблема в том, что существуют разные шаблоны, созданные `` сжатием '' ipv6 - начало, середина и конец двоеточия, кроме того, если вы использовали двойное двоеточие, вы не можете использовать его снова, помимо всего двоеточия до и после двойного суммирования. Perl 6 может справиться с этим, но это выходит далеко за рамки синтаксиса PCRE. (PS - я не считаю встроенный ipv4 в конце, он длиннее раздела ipv6!) - person Gerard ONeill; 12.04.2017

Это также улавливает loopback (:: 1) и адреса ipv6. изменил {} на + и поставил: внутри первой квадратной скобки.

([a-f0-9:]+:+)+[a-f0-9]+

протестировано с помощью ifconfig -a output http://regexr.com/

Параметр o терминала Unix или Mac OSx возвращает только соответствующий вывод (ipv6), включая :: 1

ifconfig -a | egrep -o '([a-f0-9:]+:+)+[a-f0-9]+'

Получить все IP-адреса (IPv4 ИЛИ IPv6) и распечатать совпадение на термине unix OSx

ifconfig -a | egrep -o '([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) | (([a-f0-9:]+:+)+[a-f0-9]+)'
person Rohit Malgaonkar    schedule 20.05.2016
comment
Мне нравится простота. В конечном итоге это сработало для меня: ip a | grep -Po '[\w:]+:+[\w:]+' - person Noam Manos; 07.01.2019
comment
Юмор приветствуется! - person Soumya Kanti; 08.01.2019
comment
Когда я запускаю ipconfig / all, мой IP-адрес заканчивается на% 10, это выражение не соответствует этой части? - person Peter; 22.05.2020

Я бы настоятельно поддержал ответ Фрэнка Крюгера.

Хотя вы говорите, что вам нужно регулярное выражение для соответствия IPv6-адресу, я предполагаю, что вам действительно нужно иметь возможность проверить, является ли данная строка действительным IPv6-адресом. Здесь есть тонкое, но важное различие.

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

По возможности используйте существующую библиотеку. В библиотеке будет меньше ошибок, и ее использование приведет к меньшему количеству кода, который вам придется поддерживать.

Регулярное выражение, предложенное Factor Mystic, длинное и сложное. Скорее всего, это сработает, но вы также должны подумать, как бы вы справились, если он неожиданно выйдет из строя. Я пытаюсь подчеркнуть, что если вы не можете самостоятельно сформировать требуемое регулярное выражение, вы не сможете легко отладить его.

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

Будьте осторожны при использовании регулярных выражений, функции которых вы не можете объяснить кому-либо.

person Jon Cram    schedule 10.09.2008
comment
Использование двух регулярных выражений, либерального выражения и выражения исключений для перехвата недопустимых адресов, разрешенных первым, может быть проще, чем одно выражение (return ex1.match(S) && ! ex2.match(S)). - person Raedwald; 02.04.2013
comment
Вы предполагаете, что он проверяет отдельные IP-адреса, когда почти наверняка ищет IP-адреса в большом блоке текста. - person Navin; 06.04.2016

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

^([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})$

чтобы ответить "это действующий ipv6", мне кажется, что это нормально. Чтобы разбить это на части ... забудьте об этом. Я пропустил неуказанный адрес (: :), поскольку в моей базе данных нет смысла иметь «неуказанный адрес».

начало: ^([0-9A-Fa-f]{0,4}:){2,7} ‹- соответствует сжимаемой части, мы можем перевести это как: от 2 до 7 двоеточие, между которыми может быть шестнадцатеричное число.

за которым следует: [0-9A-Fa-f]{1,4}$ ‹- шестнадцатеричное число (ведущий 0 опущен) ИЛИ ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}‹ - адрес IPv4

person Remi Morin    schedule 19.02.2013
comment
+1 за то, что на самом деле придерживались вопроса OP и представляли относительно красивое регулярное выражение, которое отчасти работает. - person xebeche; 11.06.2013
comment
Это не соответствует :: 1 - person lsalamon; 12.08.2014
comment
Хм? В синтаксисе регулярных выражений Java он соответствует: start() = 0, end() = 3 group(0) = "::1" group(1) = ":" group(2) = "1" group(3) = "null" group(4) = "null" group(5) = "null" - person Remi Morin; 05.11.2014
comment
Где-то еще кто-то уведомляет меня о проблеме с моим регулярным выражением, сжатая часть :: может появляться только один раз. Таким образом, :: 1 :: 2 будет соответствовать моему регулярному выражению, но это недействительный IPV6. Второе регулярное выражение может проверить этот случай. Полная рекомендация заключалась в использовании парсера с отслеживанием состояния для проверки. Я согласен с тем, что полученный код будет легче читать и поддерживать (и кто-то, вероятно, уже где-то закодировал его в открытом доступе). - person Remi Morin; 07.04.2015

Это регулярное выражение будет соответствовать действительным адресам IPv6 и IPv4 в соответствии с реализацией регулярного выражения GNU C ++ с использованием режима REGULAR EXTENDED:

"^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:)))(%.+)?\s*$"
person janCoffee    schedule 06.04.2011

Остерегаться! В Java использование InetAddress и связанных классов (Inet4Address, Inet6Address, URL) может включать сетевой трафик! Например. Разрешение DNS (URL.equals, InetAddress из строки!). Этот звонок может занять много времени и блокируется!

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

S - сегмент IPv6 = [0-9a-f]{1,4}

I - IPv4 = (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})

Схема (первая часть соответствует IPv6-адресам с суффиксом IPv4, вторая часть соответствует IPv6-адресам, последняя часть соответствует индексу зоны):

(
(
::(S:){0,5}|
S::(S:){0,4}|
(S:){2}:(S:){0,3}|
(S:){3}:(S:){0,2}|
(S:){4}:(S:)?|
(S:){5}:|
(S:){6}
)
I

|

:(:|(:S){1,7})|
S:(:|(:S){1,6})|
(S:){2}(:|(:S){1,5})|
(S:){3}(:|(:S){1,4})|
(S:){4}(:|(:S){1,3})|
(S:){5}(:|(:S){1,2})|
(S:){6}(:|(:S))|
(S:){7}:|
(S:){7}S
)

(?:%[0-9a-z]+)?

И здесь может быть регулярное выражение (без учета регистра, окружение тем, что когда-либо было необходимо, например, начало / конец строки и т. Д.):

(?:
(?:
::(?:[0-9a-f]{1,4}:){0,5}|
[0-9a-f]{1,4}::(?:[0-9a-f]{1,4}:){0,4}|
(?:[0-9a-f]{1,4}:){2}:(?:[0-9a-f]{1,4}:){0,3}|
(?:[0-9a-f]{1,4}:){3}:(?:[0-9a-f]{1,4}:){0,2}|
(?:[0-9a-f]{1,4}:){4}:(?:[0-9a-f]{1,4}:)?|
(?:[0-9a-f]{1,4}:){5}:|
(?:[0-9a-f]{1,4}:){6}
)
(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}
(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})|

:(?::|(?::[0-9a-f]{1,4}){1,7})|
[0-9a-f]{1,4}:(?::|(?::[0-9a-f]{1,4}){1,6})|
(?:[0-9a-f]{1,4}:){2}(?::|(?::[0-9a-f]{1,4}){1,5})|
(?:[0-9a-f]{1,4}:){3}(?::|(?::[0-9a-f]{1,4}){1,4})|
(?:[0-9a-f]{1,4}:){4}(?::|(?::[0-9a-f]{1,4}){1,3})|
(?:[0-9a-f]{1,4}:){5}(?::|(?::[0-9a-f]{1,4}){1,2})|
(?:[0-9a-f]{1,4}:){6}(?::|(?::[0-9a-f]{1,4}))|
(?:[0-9a-f]{1,4}:){7}:|
(?:[0-9a-f]{1,4}:){7}[0-9a-f]{1,4}
)

(?:%[0-9a-z]+)?
person user2623580    schedule 27.07.2013

Если вы используете Perl, попробуйте Net :: IPv6Addr

use Net::IPv6Addr;

if( defined Net::IPv6Addr::is_ipv6($ip_address) ){
  print "Looks like an ipv6 address\n";
}

NetAddr :: IP

use NetAddr::IP;

my $obj = NetAddr::IP->new6($ip_address);

Проверить :: IP

use Validate::IP qw'is_ipv6';

if( is_ipv6($ip_address) ){
  print "Looks like an ipv6 address\n";
}
person Brad Gilbert    schedule 13.09.2008
comment
Или Data :: Validate :: IP search.cpan.org/~neely/Data-Validate-IP-0.11/lib/Data/Validate/. - person Calimo; 16.12.2010

Простое регулярное выражение, которое будет соответствовать, но я бы не рекомендовал для какой-либо проверки, это следующее:

([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}

Обратите внимание, что это соответствует сжатию в любом месте адреса, но не соответствует адресу обратной связи :: 1. Я считаю это разумным компромиссом, чтобы упростить регулярное выражение.

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

person JinnKo    schedule 13.04.2013
comment
Вы имели в виду A-F, а не A-Z! Также обратите внимание, что вы исключаете обозначение с четырьмя точками. - person xebeche; 11.06.2013

Следующее регулярное выражение предназначено только для IPv6. Группа 1 совпадает с IP.

(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})
person Jitendra Gosavi    schedule 17.05.2018
comment
+1 Не всегда обязательно иметь идеальное суперсложное регулярное выражение, которое человек не может понять. Я буду использовать этот, потому что я понимаю, что он делает, и в моем случае я могу быть уверен, что если у меня что-то похожее на действительный ipv6, значит, это действительный ipv6. - person David L.; 27.01.2019
comment
это не совпадет, скажем: fe80 :: 1 или 2342: 32fd :: 2d32 - person James; 24.04.2019
comment
Регулярное выражение соответствует: 2020-09-09 16:36:10, 978 INFO success: nginx вошел в состояние RUNNING, процесс не работал ›более 1 секунды (startsecs). - person Kaymaz; 21.10.2020
comment
@Kaymaz использует некоторый контекст в вашем регулярном выражении. Сжатие не может быть легко выражено с помощью регулярного выражения, как вы видите в ответах вверху. - person grin; 05.03.2021

Регулярные выражения для ipv6 могут быть очень сложными, если учесть адреса со встроенным ipv4 и сжатые адреса, как вы можете видеть из некоторых из этих ответов.

Библиотека Java IPAddress с открытым исходным кодом проверяет все стандартные представления IPv6 и IPv4, а также поддерживает префикс- длина (и проверка таковой). Отказ от ответственности: я являюсь руководителем проекта этой библиотеки.

Пример кода:

        try {
            IPAddressString str = new IPAddressString("::1");
            IPAddress addr = str.toAddress();
            if(addr.isIPv6() || addr.isIPv6Convertible()) {
                IPv6Address ipv6Addr = addr.toIPv6();
            }
            //use address
        } catch(AddressStringException e) {
            //e.getMessage has validation error
        }
person Sean F    schedule 18.12.2017

В Scala используйте хорошо известные валидаторы Apache Commons.

http://mvnrepository.com/artifact/commons-validator/commons-validator/1.4.1

libraryDependencies += "commons-validator" % "commons-validator" % "1.4.1"


import org.apache.commons.validator.routines._

/**
 * Validates if the passed ip is a valid IPv4 or IPv6 address.
 *
 * @param ip The IP address to validate.
 * @return True if the passed IP address is valid, false otherwise.
 */  
 def ip(ip: String) = InetAddressValidator.getInstance().isValid(ip)

После проверки метода ip(ip: String):

"The `ip` validator" should {
  "return false if the IPv4 is invalid" in {
    ip("123") must beFalse
    ip("255.255.255.256") must beFalse
    ip("127.1") must beFalse
    ip("30.168.1.255.1") must beFalse
    ip("-1.2.3.4") must beFalse
  }

  "return true if the IPv4 is valid" in {
    ip("255.255.255.255") must beTrue
    ip("127.0.0.1") must beTrue
    ip("0.0.0.0") must beTrue
  }

  //IPv6
  //@see: http://www.ronnutter.com/ipv6-cheatsheet-on-identifying-valid-ipv6-addresses/
  "return false if the IPv6 is invalid" in {
    ip("1200::AB00:1234::2552:7777:1313") must beFalse
  }

  "return true if the IPv6 is valid" in {
    ip("1200:0000:AB00:1234:0000:2552:7777:1313") must beTrue
    ip("21DA:D3:0:2F3B:2AA:FF:FE28:9C5A") must beTrue
  }
}
person OliverKK    schedule 06.10.2015
comment
Интересно, что он утверждает, что проверяет, что это действительный адрес, Проверяет, является ли переданный IP действительным адресом IPv4 или IPv6., но на самом деле он только проверяет, отформатирован ли он как действительный адрес. Например, 1200:0000:AB00:1234:0000:2552:7777:1313 - допустимый формат для IPv6-адреса, но он не является действительным IPv6-адресом, как возвращает тестовый метод. Готов поспорить, он подумает, что 241.54.113.65 - действительный адрес IPv4. - person Ron Maupin; 03.11.2015

Глядя на шаблоны, включенные в другие ответы, есть ряд хороших шаблонов, которые можно улучшить, ссылаясь на группы и используя опережающие просмотры. Вот пример шаблона, который ссылается на себя, который я бы использовал в PHP, если бы мне пришлось:

^(?<hgroup>(?<hex>[[:xdigit:]]{0,4}) # grab a sequence of up to 4 hex digits
                                     # and name this pattern for usage later
     (?<!:::):{1,2})                 # match 1 or 2 ':' characters
                                     # as long as we can't match 3
 (?&hgroup){1,6} # match our hex group 1 to 6 more times
 (?:(?:
    # match an ipv4 address or
    (?<dgroup>2[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(?&dgroup)
    # match our hex group one last time
    |(?&hex))$

Примечание. В PHP есть встроенный фильтр для этого, который был бы лучшим решением, чем этот шаблон.

Анализ Regex101

person Steve Buzonas    schedule 11.03.2014

Я сгенерировал следующее, используя python, и работаю с модулем re. Утверждения упреждающего просмотра гарантируют, что в адресе будет правильное количество точек или двоеточий. Он не поддерживает IPv4 в нотации IPv6.

pattern = '^(?=\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$)(?:(?:25[0-5]|[12][0-4][0-9]|1[5-9][0-9]|[1-9]?[0-9])\.?){4}$|(?=^(?:[0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}$)(?![^:]*::.+::[^:]*$)(?:(?=.*::.*)|(?=\w+:\w+:\w+:\w+:\w+:\w+:\w+:\w+))(?:(?:^|:)(?:[0-9a-f]{4}|[1-9a-f][0-9a-f]{0,3})){0,8}(?:::(?:[0-9a-f]{1,4}(?:$|:)){0,6})?$'
result = re.match(pattern, ip)
if result: result.group(0)
person Mike Wilmes    schedule 03.10.2016

В Java можно использовать библиотечный класс sun.net.util.IPAddressUtil:

IPAddressUtil.isIPv6LiteralAddress(iPaddress);
person user463639    schedule 01.10.2010
comment
sun.net. * - это частный API. - person David Kocher; 19.05.2015

Трудно найти регулярное выражение, которое работало бы для всех случаев IPv6. Обычно их сложно поддерживать, их нелегко читать и они могут вызвать проблемы с производительностью. Поэтому я хочу поделиться разработанным мною альтернативным решением: Регулярное выражение (RegEx) для IPv6 отдельно от IPv4

Теперь вы можете спросить: «Этот метод находит только IPv6, как я могу найти IPv6 в тексте или файле?» Вот методы решения этой проблемы.

Примечание. Если вы не хотите использовать класс IPAddress в .NET, вы также можете заменить его на мой метод. Он также охватывает сопоставленный IPv4 и особые случаи, в то время как IPAddress не распространяется.

class IPv6
{
    public List<string> FindIPv6InFile(string filePath)
    {
        Char ch;
        StringBuilder sbIPv6 = new StringBuilder();
        List<string> listIPv6 = new List<string>();
        StreamReader reader = new StreamReader(filePath);
        do
        {
            bool hasColon = false;
            int length = 0;

            do
            {
                ch = (char)reader.Read();

                if (IsEscapeChar(ch))
                    break;

                //Check the first 5 chars, if it has colon, then continue appending to stringbuilder
                if (!hasColon && length < 5)
                {
                    if (ch == ':')
                    {
                        hasColon = true;
                    }
                    sbIPv6.Append(ch.ToString());
                }
                else if (hasColon) //if no colon in first 5 chars, then dont append to stringbuilder
                {
                    sbIPv6.Append(ch.ToString());
                }

                length++;

            } while (!reader.EndOfStream);

            if (hasColon && !listIPv6.Contains(sbIPv6.ToString()) && IsIPv6(sbIPv6.ToString()))
            {
                listIPv6.Add(sbIPv6.ToString());
            }

            sbIPv6.Clear();

        } while (!reader.EndOfStream);
        reader.Close();
        reader.Dispose();

        return listIPv6;
    }

    public List<string> FindIPv6InText(string text)
    {
        StringBuilder sbIPv6 = new StringBuilder();
        List<string> listIPv6 = new List<string>();

        for (int i = 0; i < text.Length; i++)
        {
            bool hasColon = false;
            int length = 0;

            do
            {
                if (IsEscapeChar(text[length + i]))
                    break;

                //Check the first 5 chars, if it has colon, then continue appending to stringbuilder
                if (!hasColon && length < 5)
                {
                    if (text[length + i] == ':')
                    {
                        hasColon = true;
                    }
                    sbIPv6.Append(text[length + i].ToString());
                }
                else if (hasColon) //if no colon in first 5 chars, then dont append to stringbuilder
                {
                    sbIPv6.Append(text[length + i].ToString());
                }

                length++;

            } while (i + length != text.Length);

            if (hasColon && !listIPv6.Contains(sbIPv6.ToString()) && IsIPv6(sbIPv6.ToString()))
            {
                listIPv6.Add(sbIPv6.ToString());
            }

            i += length;
            sbIPv6.Clear();
        }

        return listIPv6;
    }

    bool IsEscapeChar(char ch)
    {
        if (ch != ' ' && ch != '\r' && ch != '\n' && ch!='\t')
        {
            return false;
        }

        return true;
    }

    bool IsIPv6(string maybeIPv6)
    {
        IPAddress ip;
        if (IPAddress.TryParse(maybeIPv6, out ip))
        {
            return ip.AddressFamily == AddressFamily.InterNetworkV6;
        }
        else
        {
            return false;
        }
    }

}
person Nuh Metin Güler    schedule 03.02.2015

InetAddressUtils имеет все определенные шаблоны. В итоге я использовал их шаблон напрямую и вставляю его сюда для справки:

private static final String IPV4_BASIC_PATTERN_STRING =
        "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + // initial 3 fields, 0-255 followed by .
         "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; // final field, 0-255

private static final Pattern IPV4_PATTERN =
    Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING + "$");

private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros
        Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING + "$");

private static final Pattern IPV6_STD_PATTERN =
    Pattern.compile(
            "^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$");

private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
    Pattern.compile(
            "^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)" + // 0-6 hex fields
             "::" +
             "(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields 
person user4604205    schedule 25.02.2015
comment
Последнее регулярное выражение допускает 6 шестнадцатеричных полей плюс '::' плюс 6 других шестнадцатеричных полей, что сделало бы его слишком длинным IPv6-адресом ... - person Patrick Mevzek; 21.10.2020

Используете Ruby? Попробуй это:

/^(((?=.*(::))(?!.*\3.+\3))\3?|[\dA-F]{1,4}:)([\dA-F]{1,4}(\3|:\b)|\2){5}(([\dA-F]{1,4}(\3|:\b|$)|\2){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})\z/i
person Ahamx    schedule 16.01.2013

В зависимости от ваших потребностей приблизительное значение, например:

[0-9a-f:]+

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

person Bill Lipa    schedule 30.08.2016

Для пользователей PHP 5.2+ filter_var отлично работает.

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

$is_ip4address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== FALSE);
$is_ip6address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE);
person Wireblue    schedule 18.11.2013

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

(?=([0-9a-f]+(:[0-9a-f])*)?(?P<wild>::)(?!([0-9a-f]+:)*:))(::)?([0-9a-f]{1,4}:{1,2}){0,6}(?(wild)[0-9a-f]{0,4}|[0-9a-f]{1,4}:[0-9a-f]{1,4})
person user1977022    schedule 29.09.2014

Вы можете использовать инструменты оболочки ipextract, которые я сделал для этой цели. Они основаны на regexp и grep.

Использование:

$ ifconfig | ipextract6
fe80::1%lo0
::1
fe80::7ed1:c3ff:feec:dee1%en0
person Phil L.    schedule 22.02.2014

Просто сопоставление локальных из источника с включенными квадратными скобками. Я знаю, что это не так исчерпывающе, но в javascript другим было трудно отследить проблемы, в первую очередь неработающие, поэтому, похоже, это дает мне то, что мне нужно сейчас. лишние заглавные буквы A-F также не нужны.

^\[([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})\]

Версия Джиннко упрощена, и я лучше ее понимаю.

person Master James    schedule 09.04.2017

Как указано выше, другой способ получить проверяющий синтаксический анализатор IPv6 - использовать программирование. Вот тот, который полностью соответствует RFC-4291 и RFC-5952. Я написал этот код на ANSI C (работает с GCC, прошел тесты на Linux - работает с clang, прошел тесты на FreeBSD). Таким образом, он полагается только на стандартную библиотеку ANSI C, поэтому его можно компилировать везде (я использовал его для синтаксического анализа IPv6 внутри модуля ядра с FreeBSD).

// IPv6 textual representation validating parser fully compliant with RFC-4291 and RFC-5952
// BSD-licensed / Copyright 2015-2017 Alexandre Fenyo

#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

typedef enum { false, true } bool;

static const char hexdigits[] = "0123456789abcdef";
static int digit2int(const char digit) {
  return strchr(hexdigits, digit) - hexdigits;
}

// This IPv6 address parser handles any valid textual representation according to RFC-4291 and RFC-5952.
// Other representations will return -1.
//
// note that str input parameter has been modified when the function call returns
//
// parse_ipv6(char *str, struct in6_addr *retaddr)
// parse textual representation of IPv6 addresses
// str:     input arg
// retaddr: output arg
int parse_ipv6(char *str, struct in6_addr *retaddr) {
  bool compressed_field_found = false;
  unsigned char *_retaddr = (unsigned char *) retaddr;
  char *_str = str;
  char *delim;

  bzero((void *) retaddr, sizeof(struct in6_addr));
  if (!strlen(str) || strchr(str, ':') == NULL || (str[0] == ':' && str[1] != ':') ||
      (strlen(str) >= 2 && str[strlen(str) - 1] == ':' && str[strlen(str) - 2] != ':')) return -1;

  // convert transitional to standard textual representation
  if (strchr(str, '.')) {
    int ipv4bytes[4];
    char *curp = strrchr(str, ':');
    if (curp == NULL) return -1;
    char *_curp = ++curp;
    int i;
    for (i = 0; i < 4; i++) {
      char *nextsep = strchr(_curp, '.');
      if (_curp[0] == '0' || (i < 3 && nextsep == NULL) || (i == 3 && nextsep != NULL)) return -1;
      if (nextsep != NULL) *nextsep = 0;
      int j;
      for (j = 0; j < strlen(_curp); j++) if (_curp[j] < '0' || _curp[j] > '9') return -1;
      if (strlen(_curp) > 3) return -1;
      const long val = strtol(_curp, NULL, 10);
      if (val < 0 || val > 255) return -1;
      ipv4bytes[i] = val;
      _curp = nextsep + 1;
    }
    sprintf(curp, "%x%02x:%x%02x", ipv4bytes[0], ipv4bytes[1], ipv4bytes[2], ipv4bytes[3]);
  }

  // parse standard textual representation
  do {
    if ((delim = strchr(_str, ':')) == _str || (delim == NULL && !strlen(_str))) {
      if (delim == str) _str++;
      else if (delim == NULL) return 0;
      else {
        if (compressed_field_found == true) return -1;
        if (delim == str + strlen(str) - 1 && _retaddr != (unsigned char *) (retaddr + 1)) return 0;
        compressed_field_found = true;
        _str++;
        int cnt = 0;
        char *__str;
        for (__str = _str; *__str; ) if (*(__str++) == ':') cnt++;
        unsigned char *__retaddr = - 2 * ++cnt + (unsigned char *) (retaddr + 1);
        if (__retaddr <= _retaddr) return -1;
        _retaddr = __retaddr;
      }
    } else {
      char hexnum[4] = "0000";
      if (delim == NULL) delim = str + strlen(str);
      if (delim - _str > 4) return -1;
      int i;
      for (i = 0; i < delim - _str; i++)
        if (!isxdigit(_str[i])) return -1;
        else hexnum[4 - (delim - _str) + i] = tolower(_str[i]);
      _str = delim + 1;
      *(_retaddr++) = (digit2int(hexnum[0]) << 4) + digit2int(hexnum[1]);
      *(_retaddr++) = (digit2int(hexnum[2]) << 4) + digit2int(hexnum[3]);
    }
  } while (_str < str + strlen(str));
  return 0;
}
person Alexandre Fenyo    schedule 24.07.2017

Это будет работать для IPv4 и IPv6:

^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$
person Chris    schedule 06.12.2013
comment
Он сопоставляет недопустимые адреса с двумя экземплярами ::. например 2404:6800::4003:c02::8a - person nhahtdh; 03.09.2015
comment
соответствует недопустимому IPv4 666.666.666.666 - person Ryan Williams; 22.01.2018

Попробуйте этот небольшой однострочник. Он должен соответствовать только действительным несжатым / сжатым адресам IPv6 (без гибридов IPv4)

/(?!.*::.*::)(?!.*:::.*)(?!:[a-f0-9])((([a-f0-9]{1,4})?[:](?!:)){7}|(?=(.*:[:a-f0-9]{1,4}::|^([:a-f0-9]{1,4})?::))(([a-f0-9]{1,4})?[:]{1,2}){1,6})[a-f0-9]{1,4}/
person Carlos Velazquez    schedule 19.06.2016
comment
Фактически, допустимые IPv6-адреса включают несжатый, сжатый, несжатый гибридный и сжатый гибридный. На самом деле требуется гораздо больше, чем то, что вам нужно, чтобы фактически сопоставить любое действительное текстовое представление IPv6-адреса. - person Ron Maupin; 19.06.2016

Регулярное выражение позволяет использовать ведущие нули в частях IPv4.

Некоторые дистрибутивы Unix и Mac преобразуют эти сегменты в восьмеричные числа.

Я предлагаю использовать 25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d в качестве сегмента IPv4.

person Aeron    schedule 15.10.2009

Если вам нужны только обычные IP-адреса (без косой черты), вот:

^(?:[0-9a-f]{1,4}(?:::)?){0,7}::[0-9a-f]+$

Я использую его для подсветки синтаксиса в приложении для редактирования файлов hosts. Работает как оберег.

person Harry    schedule 24.07.2013
comment
Ни в коем случае, чтобы это когда-либо работало прилично, он не может сопоставить один адрес ipv6 с одним двоеточием в нем, все ваши совпадения находятся в двойных двоеточиях, и вам явно требуется двойное двоеточие для вашей последней группы, суммирование может происходить где угодно .. ... - person KillianDS; 24.07.2013
comment
По-прежнему неверно, но даже в этом случае вы в конечном итоге будете повторять ответ JinnKo, который достаточно хорош для простых целей, но все же имеет недостатки (не улавливает двойное суммирование и не допускает четырехугольники с точками, ни localhost, ни :: termination,. ..) - person KillianDS; 24.07.2013