在 Linux 中,您可以使用带有 grep 的正则表达式从文件中提取 IP 地址。grep 命令具有 -E(扩展正则表达式)选项,以允许它将模式解释为扩展正则表达式。
IPv4 地址的格式是一个 32 位数字地址,一次分组 8 位(称为八位字节),每个位用点分隔。每个八位字节的范围为 0-255。
您可以创建一个正则表达式来查找由点分隔的 4 个 1-3 位数字块,如下所示:
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' ips.txt
排序IP地址:
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' ips.txt | sort
该命令在大多数情况下都可以,但如果有一个无效的 IP 地址,如 265.168.1.2(请记住八位字节不能高于 255),它仍然会找到它。
这是一个例子:
$ grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' ips.txt
123.321.234.712
999.999.999.999
192.168.5.5
我们必须扩展这个正则表达式来告诉它忽略 256 或更高的数字。这是一个仅提取有效 IP 地址的正则表达式示例。
$ grep -E '^((25[0-5]|2[0-4][0-9]|[1]?[1-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[1]?[1-9]?[0-9])$' ips.txt
192.168.5.5
上面做得很好,但仍然存在问题。它不会找到带有前导零的 IP 地址,也不会找到带有 0 作为八位字节唯一编号的 IP 地址。例如,此正则表达式将不匹配 10.0.0.5。
为了找到只能提取有效 IP 地址的正则表达式,我们必须竭尽全力验证模式中的每个八位字节。这是一个例子:
$ grep "([^.]|^)([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5]).([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5]).([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5]).([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])([^.]|$)" ips.txt
192.168.5.5
10.0.0.4
即使是上面的也不是没有缺陷。
从 IPv4 和 IPv6 中的地址中删除前导零是一项行业标准。但仅仅因为这是表示 IPv4 地址的标准方式,并不意味着每个人都会这样做。
例如,您可以用三个零来表示一个零填充的八位字节。
10.000.000.5 = 10.0.0.5
这两个地址都可以在网络上正常工作,但即使 ping 也会删除前导零。
$ ping 10.000.000.5
PING 10.000.000.5 (10.0.0.5) 56(84) bytes of data.
64 bytes from 10.0.0.5: icmp_seq=1 ttl=64 time=0.252 ms
64 bytes from 10.0.0.5: icmp_seq=2 ttl=64 time=0.312 ms
Red Hat 的一些人开发了一个名为 ipcalc 的小工具。它最初是为计算主机的 IP 信息而构建的,但也可用于 IP 地址验证。果然,这个工具也会调用带有前导零的 IP 地址一个无效的 IP 地址。
$ ipcalc -c 10.000.000.5
ipcalc: bad IPv4 address: 10.000.000.5
如您所见,使用 grep 和正则表达式从文件中提取 IP 地址相当容易。确保匹配的模式是有效的 IP 地址并不容易。