Регулярное выражение, соответствующее допустимым адресам IPv6
У меня возникли проблемы с написанием регулярного выражения, которое соответствует допустимым адресам IPv6, в том числе в их сжатой форме (с ::
или ведущие нули, опущенные из каждой пары байтов).
может ли кто-нибудь предложить регулярное выражение, которое выполняло бы это требование?
Я рассматриваю возможность расширения каждой пары байтов и сопоставления результата с более простым регулярным выражением.
30 ответов:
если я могу обойти ваш вопрос, рассмотрите возможность использования понятия адреса вашей сетевой библиотеки для анализа и проверки ошибок.
Я думаю, что в какой-то момент Вы захотите что-то сделать с этими адресами, так почему бы просто не перейти прямо к источнику и убедиться, что ваша сетевая библиотека поймет адрес? Это лучше, чем просто надеяться, что любое регулярное выражение, которое будет опубликовано здесь, будет соответствовать концепции вашей реализации адреса.
В Java у нас есть
InetAddress
. В .NET у нас естьIPAddress
. В .NET, у вас даже естьTryParse
наIPAddress
класс чтобы сделать этот тест для вас!bool IsIP6(string addr) { IPAddress ip; if (IPAddress.TryParse(addr, out ip)) { return ip.AddressFamily == AddressFamily.InterNetworkV6; } else { return false; } }
Я не смог получить ответ @Factor Mystic для работы с регулярными выражениями POSIX, поэтому я написал тот, который работает с регулярными выражениями POSIX и регулярными выражениями PERL.
Он должен соответствовать:
- IPv6-адресов
- ноль сжатых IPv6 адресов (раздел 2.2 rfc5952)
- локальные IPv6-адреса с индексом зоны (раздел 11 rfc4007)
- Протокол IPv4-Адрес IPv6 Встроен (раздел 2 rfc6052)
- IPv4-сопоставленные IPv6 адреса (раздел 2.1 rfc2765)
- IPv4-переведенные адреса (раздел 2.1 rfc2765)
Регулярное Выражение 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
следующие проверят 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'
от "регулярное выражение 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)
похоже, что вы можете использовать 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.
Я бы сильно поддержал ответ от Фрэнк Крюгер.
хотя вы говорите, что вам нужно регулярное выражение для соответствия IPv6-адресу, я предполагаю, что вам действительно нужно, чтобы проверить, является ли данная строка допустимым IPv6-адресом. Здесь есть тонкое, но важное различие.
существует несколько способов проверить, является ли данная строка допустимым адресом IPv6, а регулярное выражение-только одним решением.
использовать существующая библиотека, если можно. Библиотека будет иметь меньше ошибок и ее использование приведет к меньше кода для вас, чтобы сохранить.
регулярное выражение, предложенное Фактор Мистик это долго и сложно. Это, скорее всего, работает, но вы также должны рассмотреть, как вы справитесь, если он неожиданно терпит неудачу. Дело в том, что если вы не можете сформировать необходимое регулярное выражение самостоятельно, вы не сможете легко отладить его.
Если у вас нет подходящего библиотека может быть лучше написать свою собственную процедуру проверки IPv6, которая не зависит от регулярных выражений. Если вы пишете это, вы это понимаете, и если вы это понимаете, вы можете добавить комментарии, чтобы объяснить это, чтобы другие могли также понять и впоследствии поддерживать его.
будьте осторожны при использовании регулярного выражения, функциональность которого вы не можете объяснить кому-то еще.
это регулярное выражение будет соответствовать допустимым адресам IPv6 и IPv4 в соответствии с реализацией регулярного выражения GNU C++ с использованием обычного расширенного режима:
"^\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*$"
Я не эксперт 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}
затем:
[0-9A-Fa-f]{1,4}$
((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}
остерегайтесь! в Java использование InetAddress и связанных классов (Inet4Address, INET6ADDRESS, URL) может включать сетевой трафик! например, разрешение DNS (URL.равно, 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-адресам, последний patrt индекс зоны):
( ( ::(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]+)?
Если вы используете Perl try Net:: IPv6Addr
use Net::IPv6Addr; if( defined Net::IPv6Addr::is_ipv6($ip_address) ){ print "Looks like an ipv6 address\n"; }
use NetAddr::IP; my $obj = NetAddr::IP->new6($ip_address);
use Validate::IP qw'is_ipv6'; if( is_ipv6($ip_address) ){ print "Looks like an ipv6 address\n"; }
Это ловит loopback (:: 1), а также и IPv6-адреса. изменил {} на + и поставил: внутри первой квадратной скобки.
([A-f0-9:]+:+)+[A-f0-9]+
протестировано на выходе ifconfig-a http://regexr.com/
Unix или Mac OSx terminal o опция возвращает только соответствующий выход (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]+)'
на Скала используйте хорошо известные валидаторы 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 } }
простое регулярное выражение, которое будет соответствовать, но я бы не рекомендовал для проверки любого рода это:
([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}
обратите внимание, что это соответствует сжатию в любом месте адреса, хотя оно не будет соответствовать адресу обратной связи ::1. Я нахожу это разумным компромиссом, чтобы сохранить регулярное выражение простым.
Я успешно использую это в iTerm2 умные правила выбора для четырехкратного щелчка IPv6 адреса.
трудно найти регулярное выражение, которое работает для всех случаев 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; } } }
глядя на шаблоны, включенные в другие ответы есть ряд хороших шаблонов, которые могут быть улучшены путем ссылки на группы и использования lookaheads. Вот пример шаблона, который является самостоятельной ссылкой, которую я бы использовал в 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 имеет встроенный фильтр для этого, который был бы лучшим решением, чем это узор.
С Помощью Ruby? Попробуйте это:
/^(((?=.*(::))(?!.*.+))?|[\dA-F]{1,4}:)([\dA-F]{1,4}(|:\b)|){5}(([\dA-F]{1,4}(|:\b|$)|){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})\z/i
в зависимости от ваших потребностей, приближение как:
[0-9a-f:]+
может быть достаточно (как, например, с простым захватом файла журнала.)
следующее регулярное выражение предназначено только для IPv6. Группа 1 соответствует IP.
(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})
в Java можно использовать класс библиотеки
sun.net.util.IPAddressUtil
:IPAddressUtil.isIPv6LiteralAddress(iPaddress);
для 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);
Это будет работать для IPv4 и IPv6:
^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$
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
вот что я придумал, используя немного вперед и именованные группы. Это, конечно, просто 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})
можно использовать инструменты оболочки ipextract Я сделал для этой цели. Они основаны на регулярных выражениях и grep.
использование:
$ ifconfig | ipextract6 fe80::1%lo0 ::1 fe80::7ed1:c3ff:feec:dee1%en0
Я создал следующее С помощью 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)
просто сопоставление локальных из источника с квадратными скобками включены. Я знаю, что это не так всеобъемлюще, но в javascript другим было трудно отслеживать проблемы, прежде всего, что не работает, поэтому это, похоже, дает мне то, что мне нужно сейчас. дополнительные капиталы A-F также не нужны.
Jinnko является упрощенной и лучше, я вижу.^\[([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})\]
как указано выше, другой способ получить текстовое представление 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; }
регулярные выражения для 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 }