有効なIPv6アドレスに一致する正規表現


111

有効なIPv6アドレスに一致する正規表現(圧縮された形式(::各バイトペアの先頭のゼロが省略されている、または省略されている))を含む正規表現を書くのに問題があります。

誰かが要件を満たす正規表現を提案できますか?

各バイトペアを拡張し、その結果をより単純な正規表現と照合することを検討しています。



以下のすべての回答を試してみましたが、私のすべてのテストケースで機能するわけではありません。また、要求されなかったIPv4も含まれています。:私は、これは、これまで最もクリーンソリューションであることがわかってきたstackoverflow.com/a/21944928/3112803
gfrobenius

回答:


251

@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]))

読みやすくするために、主なORポイントで分割された上記の正規表現は次のようになります。

# 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


3
IPv4の正規表現が次のようなIPと一致しない127.000.000.001
Kentzo

21
IPv4セグメントには先行ゼロを含めないでください。先行ゼロが存在する場合、IPv4セグメントは8進数で解釈される必要があります。したがって、上記のIPV4SEGは「000」を許可しないという点で正しいです。ただし、許可しない '00'は許可されます。
パー

3
ブラウザで期待どおりに機能しませんでした。reg.test( '3zzzzffe:1900:4545:3:200:f8ff:fe21:67cf')でも検証されましたが、これは明らかに有効なIPv6アドレスではありません。ここでは正規表現でより良い結果を持っていた:nbviewer.ipython.org/github/rasbt/python_reference/blob/master/...
Capaj

7
素晴らしいipv6正規表現。リンクローカルセクションに小さなバグが見つかりました。あなたは持っていたfe80、それはのようなものであるべき場所[fF][eE]80ffffのようなものであるべきである[fF]{4}
user2831628

4
注意してフォーマットすると、正規表現が(他のソースコードと同じように)実際に読み取り可能であることを示すための+1。
Natix

52

以下は、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'

8
ip-sの検証はFrank Kruegerが示唆するように実行できますが、このソリューションは実際に質問に答えるものです(まだ完全にはテストしていません)。また、構文的にテストするIP-sが多数ある場合テキストの行で一致する場合は、IP検証手法を使用できません。
Gyuri

こんにちは、私はこのRegExpをテストしましたが、うまくいきませんでした。Dは無効なフラグであり、削除すると「
SyntaxError

3
JavaScriptはPCRE全体ではなく、Perlスタイルの正規表現のサブセットを実装します。PCREの高度な機能がなければ、正規表現は機能しません。
MichaelRushton

2
これは、C#で私に例外を与えます
sarat

1
失敗したテストケース:FE80:0000:0000:0000:0202:B3FF:FE1E:8329この日付で最新バージョンのElixirを使用し、その下でPCREを使用します。
pmarreck 2017年

23

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

取得するためinet_ptonにIPv6をPythonにコンパイルする必要はないと思いsocket.AF_INETます。最初のパラメーターとして渡すと、IPv4アドレスも解析できます。注:これは非UNIXシステムでは機能しない可能性があります。


4
例外のタイプをexcept句で指定する必要があります。そうしないと、exceptすべてをキャッチし、無関係なエラーをマスクする可能性があります。ここのタイプはである必要がありますsocket.error
Ayman Hourieh、2009

A)ドキュメントが間違っていない限り、inet_ptonは他の例外をスローしません。B)例外が発生した場合でも、False以外に何を返しますか?
Joe Hildebrand、

2
Re:その他のエラー...ユーザーが文字列以外を渡すと、TypeErrorが食べられます。明らかにリストはipv6ではありませんが、間違ったタイプで渡していたので、おそらくそれを鯉にしたいでしょう。
Gregg Lind

1
+1これは私に大いに役立ちました。追加する必要があるいくつかの追加ポイント:1)socket.inet_ptonを使用して、IPアドレスの両方のファミリー(IPおよびIPv6)の有効性をテストできます。2)ここのドキュメント(docs.python.org/2/library/socket.html)は、これがUnixプラットフォームで利用可能であることを示唆しています。Winプラットフォームでは使用できない場合があります。
mkoistinen 2013

ジャンゴを使用すると、これが役立ちます!
eladシルバー2015

23

IPv6 regex」から:

(\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)

45
このような正規表現は「コードの匂い」であるはずです。おそらく正規表現はここでの最適なソリューションではありません。(ただし、オペはそれを要求したと思いますが...)
Thanatos 2010

10
@ user712092-そのような目障りなコードベースを見たすべての人
danielpops

2
これはREにとって完全に不必要な扱いです。それを生成したプログラムは、それが何をしているかを理解していませんでした。人間がこのようにすることは決してありません。見かけの複雑さにだまされないでください-REは実際、多くの人々にとって「ブラックマジック」ですが、別の惑星に配置する理由はありません!
チャックコラーズ2015

1しかし、OMGこれを行うには良い方法がなければならない。参考のためにPを:Railsのために、このかもしれないのヘルプ:stackoverflow.com/questions/16965697/...
は、Tilo

1
それは確かにコードのにおいです。しかし、見てみると、各正規表現がかなり簡潔であることがわかります。問題は、ipv6の「圧縮」によって作成されるさまざまなパターンがあることです-コロンの開始、中間、終了、さらに、ダブルコロンを使用した場合、合計に加えて、再度使用することはできません。ダブルの前後のコロンを合計する必要があります。Perl 6 これに取り組むことができるかもしれませんが、それはPCRE構文をはるかに超えています。(
追記

11

フランク・クルーガーからの答えを強く第二に言わなければなりません。

IPv6アドレスに一致させるには正規表現が必要だとおっしゃっていますが、実際に必要なのは、指定された文字列が有効なIPv6アドレスかどうかを確認できるようにすることです。ここには微妙ですが重要な違いがあります。

特定の文字列が有効なIPv6アドレスであるかどうかを確認する方法は複数あり、正規表現の一致は1つの解決策にすぎません。

可能であれば、既存のライブラリを使用してください。ライブラリーのバグは少なくなり、その使用により、保守するコードが少なくなります。

Factor Mysticが提案する正規表現は長く複雑です。ほとんどの場合は機能しますが、予期せず失敗した場合の対処方法も考慮する必要があります。ここで私がしようとしている点は、必要な正規表現を自分で作成できない場合、簡単にデバッグできないことです。

適切なライブラリがない場合は、正規表現に依存しない独自のIPv6検証ルーチンを作成することをお勧めします。あなたがそれを書くならあなたはそれを理解し、あなたがそれを理解したらあなたはそれを説明するコメントを追加することができます。

他の人に説明できない機能を持つ正規表現を使用する場合は、注意して行動してください。


1
2つの正規表現、リベラル式と例外式を使用して、最初のアドレスで許可されている無効なアドレスをトラップする方が、1つの式(return ex1.match(S) && ! ex2.match(S))よりも簡単かもしれません。
Raedwald 2013

4
大規模なテキストブロックでIPをほぼ確実に検索しているときに、彼が個々のIPを検証していると想定している。
Navin

8

私は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}$<-16進数(先頭の0は省略)または ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}<-Ipv4アドレス


1
+1は、実際にOPの質問に固執し、ある程度機能する比較的ハンサムな正規表現を提示するためのものです。
xebeche 2013年

1
これは「:: 1」と一致しません
lsalamon 2014

え?:Javaの正規表現syntaxtそれは試合をしにstart() = 0, end() = 3 group(0) = "::1" group(1) = ":" group(2) = "1" group(3) = "null" group(4) = "null" group(5) = "null"
レミモリン

どこか他の誰かが私の正規表現の問題を私に通知し、圧縮された部分 "::"は一度だけ現れることができます。したがって、「:: 1 :: 2」は私の正規表現と一致しますが、有効なIPV6ではありません。2番目の正規表現はこのケースを検証します。完全な推奨事項は、ステートフルパーサーを使用して検証することでした。結果のコードは読みやすく、保守しやすい(そしておそらく誰かが既にどこかでオープンソースでコード化している)ことに同意します。
Remi Morin

8

これは、ループバック(:: 1)とipv6アドレスをキャッチします。{}を+に変更し、最初の角括弧内に:を入れました。

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

ifconfig -a output http://regexr.com/でテスト済み

UnixまたはMac OSxのターミナルoオプションは、:: 1を含む一致する出力(ipv6)のみを返します

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]+)'

私はシンプルさが好きです。これは最終的に私のために働きました:ip a | grep -Po '[\w:]+:+[\w:]+'
Noam Manos

ユーモアはありがたいです!
Soumya Kanti

ipconfig / allを実行すると、IPアドレスが%10で終了します。この式はこの部分と一致しませんか?
ピーター

7

この正規表現は、正規表現が使用されている正規表現のGNU C ++実装に従って、有効なIPv6およびIPv4アドレスに一致します。

"^\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*$"

5

注意してください!Javaでは、InetAddressおよび関連クラス(Inet4Address、Inet6Address、URL)を使用すると、ネットワークトラフィックが発生する可能性があります。たとえば、DNS解決(URL.equals、InetAddress from string!)。この通話には時間がかかる可能性があり、ブロックされています!

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

回路図(最初の部分はIPv4サフィックスのあるIPv6アドレスに一致し、2番目の部分は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]+)?

4

次の正規表現は、IPv6専用です。グループ1はIPと一致します。

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

+1人間が理解できない完全な超複雑な正規表現が常に必要であるとは限りません。私はそれが何をするのかを理解しているので、これを使用します。私の場合、有効なipv6に似ているものを取得した場合、それは有効なipv6であると確信できます。
David L.

3
これは次のようには一致しません:fe80 :: 1または2342:32fd :: 2d32
James

3

一致する単純な正規表現ですが、あらゆる種類の検証にはこれはお勧めしません。

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

これは、ループバックアドレス:: 1とは一致しませんが、アドレスの任意の場所の圧縮と一致します。正規表現を単純に保つために、これは妥当な妥協案です。

これをiTerm2のスマート選択ルールで正常に使用して、IPv6アドレスをクワッドクリックします。


3
あなたが意味したのA-Fではなく、A-Z!また、ドット付きクワッド表記を除外していることにも注意してください。
xebeche 2013年

3

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

Validate :: IP

use Validate::IP qw'is_ipv6';

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


2

では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
  }
}

おもしろい、それはそれが有効なアドレスであることをチェックすると主張し、「渡されたIPが有効なIPv4またはIPv6アドレスであるかどうかを検証する。たとえば、1200:0000:AB00:1234:0000:2552:7777:1313はIPv6アドレスの有効な形式ですが、テストメソッドが返すため、有効なIPv6アドレスではありません。私はそれ241.54.113.65が有効なIPv4アドレスであると考えているに違いない。
Ron Maupin、2015年

2

他の回答に含まれているパターンを見ると、グループを参照して先読みを利用することで改善できる多くの良いパターンがあります。以下は、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分析


2

私はpythonを使用して以下を生成し、reモジュールで動作します。先読みアサーションにより、正しい数のドットまたはコロンがアドレスに表示されます。IPv6表記ではIPv4をサポートしていません。

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)

2

これらの回答のいくつかからわかるように、ipv6の正規表現は、埋め込まれたipv4のアドレスと圧縮されたアドレスを考慮すると、非常に扱いにくくなる可能性があります。

オープンソースのIPAddress Javaライブラリは、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
        }


1

すべてのIPv6ケースで機能する正規表現を見つけることは困難です。これらは通常、保守が難しく、簡単に読み取ることができず、パフォーマンスの問題を引き起こす可能性があります。したがって、私が開発した代替ソリューションを共有したいと思います。IPv4から分離したIPv6の正規表現(RegEx)

「この方法ではIPv6しか検出されません。テキストまたはファイルでIPv6を見つけるにはどうすればよいですか?」この問題の方法もここにあります。

:.NETでIPAddressクラスを使用しない場合は、それをmyメソッドで置き換えることもできます。また、マッピングされた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;
        }
    }

}

1

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 

1

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

1

あなたのニーズに応じて、次のような近似値:

[0-9a-f:]+

(たとえば、単純なログファイルのgreppingの場合と同様に)十分かもしれません。


0

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

0

これはIPv4およびIPv6で機能します。

^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$

2
無効なアドレスと2つのインスタンスが一致します::。例2404:6800::4003:c02::8a
nhahtdh

無効なIPv4に一致666.666.666.666
Ryan Williams

0

これが、先読みと名前付きグループを少し使って私が思いついたものです。もちろんこれは単なる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})


0

角かっこが含まれている起点からのローカルのものと一致するだけです。私はそれがそれほど包括的ではないことを知っていますが、JavaScriptでは、他の問題は主に機能しないという問題を追跡することが困難でした。余分な資本AFも必要ありません。

^\[([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})\]

Jinnkoのバージョンは簡略化されており、よくわかります。


0

上記のように、IPv6テキスト表現検証パーサーを取得する別の方法は、プログラミングを使用することです。以下は、RFC-4291およびRFC-5952に完全に準拠したものです。私はこのコードをANSI Cで記述しました(GCCで動作し、Linuxでのテストに合格-clangで動作し、FreeBSDでテストに合格)。したがって、それはANSI C標準ライブラリにのみ依存しているため、どこでもコンパイルできます(FreeBSDのカーネルモジュール内でIPv6解析に使用しました)。

// 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;
}

-1

この小さなワンライナーを試してください。有効な非圧縮/圧縮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}/

実際、有効なIPv6アドレスには、非圧縮、圧縮、非圧縮ハイブリッド、および圧縮ハイブリッドが含まれます。実際には、IPv6アドレスの有効なテキスト表現と実際に一致させる必要があるものよりもはるかに多くの時間がかかります。
Ron Maupin

-2

正規表現では、IPv4部分で先行ゼロを使用できます。

一部のUnixおよびMacディストリビューションでは、これらのセグメントを8進数に変換します。

25[0-5]|2[0-4]\d|1\d\d|[1-9]?\dIPv4セグメントとして使用することをお勧めします。


-2

通常のIPのみ(スラッシュなし)が必要な場合は、次のようにします。

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

私は、hostsファイルエディターアプリケーションの構文ハイライターに使用します。チャームとして機能します。


これがきちんと機能する方法はありません。単一のIPv6アドレスと単一のコロンを一致させることはできません。すべての一致は二重のコロンで行われ、最後のグループには二重のコロンを明示的に必要とします。要約はどこでも発生する可能性があります。 ……
KillianDS 2013

(?:[0-9a-f] {1,4}(?:::?)?){0,7} ::?[0-9a-f] {1,4}
ハリー

まだ間違っていますが、それでもJinnKoの答えを繰り返すことになります。これは単純な目的には十分ですが、欠点があります(二重の要約をキャッチせず、ドット付きクワッドもlocalhostも::終了も許可しません。 ..)
KillianDS 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.