Grep

匹配所有有效 IPv4 和 IPv6 地址的 grep 正則表達式

  • February 23, 2020

我正在尋找一個正則表達式,用於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 地址,我發現的最佳答案對我不起作用。使用時,該表達式不會為我輸出任何 IP 地址grep

由於這個問題顯然是模棱兩可的,我正在尋找一個組合的正則表達式。將輸出任何有效 IP 地址的一種。作為獎勵,甚至在一條線上有多個。

如果由於某種原因這不容易做到grep,我願意接受替代方案,只要它們簡單、在 BSD 系統上工作並且不需要 GNU 工具。

使用Regexp::Common包的替代基於非grep,perl的方法(可作為 FreeBSD 埠以 name 提供):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

由於您的作業系統 (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.12or中提取地址foo:127.0.0.1bar。但它將能夠從 tcpdump 的address.port形式或從通常的形式中提取它ipv4:port,並且能夠處理“混合”的 ipv4/ipv6 地址。

引用自:https://unix.stackexchange.com/questions/566517