web-dev-qa-db-ja.com

すべての有効なIPv4およびIPv6アドレスに一致するgrep正規表現

grepの正規表現を探しています。これは、IPv4およびIPv6アドレスを含む任意のファイルからそれらを除外します。 IPv4アドレスの場合、次のように動作します。

grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"

私はここで答えを持ついくつかの同様の質問があることを認識していますが、ほとんどはIPv4アドレスのみに焦点を当てています 私が見つけた最良の答え は私にとってはうまくいきません。 grepを使用すると、式はIPアドレスを出力しません。

この質問は明らかにあいまいであるため、組み合わせた正規表現を探しています。有効なIPアドレスを出力するもの。おまけとして、1行に複数のものでも。

何らかの理由でgrepでこれを行うのが容易でない場合、単純で、BSDシステムで動作し、GNU toolsを必要としない。

1
herrbischoff

Regexp :: Common パッケージを使用した代替の非grepPerlベースのアプローチ(p5-Regexp-Common):

Perl -MRegexp::Common=net -nE 'say $& while /$RE{net}{IPv4}|$RE{net}{IPv6}/g' input.txt

例:

$ cat input.txt
some words
a line with 127.0.0.1 and 192.168.1.1 in it.
more words
some line with ::1 in it.
$ Perl -MRegexp::Common=net -nE 'say $& while /$RE{net}{IPv4}|$RE{net}{IPv6}/g' input.txt
127.0.0.1
192.168.1.1
::1
2
Shawn

オペレーティングシステム(FreeBSD)にはデフォルトでコンパイラとレクサーが付属しているため(Unixシステムと同様に)、誰も理解できないお尻のような正規表現ではなく、それらを使用して小さなプログラムを作成することをお勧めします。

$ cat > ipv46.l <<'EOT'
%{
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
%}
W       [0-9A-Za-z_]+
I4      ([0-9]+[.]){3}[0-9]+
I6      ([0-9a-fA-F]|::)[0-9a-fA-F:]*{I4}?
%%
{I6}|{I4} {
        struct in6_addr a6; struct in_addr a; char b[INET6_ADDRSTRLEN];
        if(inet_pton(AF_INET6, yytext, &a6))
                printf("%s\n", inet_ntop(AF_INET6, &a6, b, sizeof b));
        else if(inet_pton(AF_INET, yytext, &a))
                printf("%s\n", inet_ntop(AF_INET, &a, b, sizeof b));
}
{W}|.|\n    ;
EOT

$ Lex ipv46.l && cc Lex.yy.c -o ipv46 -ll
$ ./ipv46 <file

$ ./ipv46
::0:0:1 1:::1 ::
::1
::
::FFFF:127.0.0.1:80
::ffff:127.0.0.1
...

これはかなり厳密です。アドレス127.0.0.1foo127.0.0.1.12またはfoo:127.0.0.1barからプルしません。しかし、tcpdumpのaddress.port形式または通常のipv4:portからプルすることができ、「混合」されたipv4/ipv6アドレスを処理できます。

2
mosvy