【问题标题】:Search file for matching IP address in Linux在 Linux 中搜索匹配 IP 地址的文件
【发布时间】:2012-03-10 03:39:14
【问题描述】:

我有分配了 IP 地址范围的文件。它看起来像这样:

...
arin|US|ipv4|8.0.0.0|16777216|19921201|allocated
arin|US|ipv4|9.0.0.0|16777216|19881216|assigned
apnic|ID|ipv4|122.200.144.0|2048|20061023|allocated
apnic|TW|ipv4|122.200.152.0|2048|20080424|allocated
apnic|AU|ipv4|122.200.160.0|4096|20061020|allocated
apnic|AU|ipv4|122.200.176.0|4096|20110121|allocated
apnic|JP|ipv4|122.200.192.0|8192|20061023|allocated
...

我的问题是是否有可能以及如何使用 grep、awk 或其他工具等工具在 Linux 中使用 IP 地址作为搜索参数从该文件中获取特定行。

例如如果搜索到的 IP 是 8.8.8.8,结果应该是:

arin|US|ipv4|8.0.0.0|16777216|19921201|allocated

编辑// 完整的 ipv4 列表可以在这里找到http://skechboy.com/ips/ipv4_table

【问题讨论】:

  • 这些字段是什么?第 5 列是网络的大小吗?
  • @dward-thomson 是的,这是特定网络中分配的 ip 数量。该数据由区域互联网注册机构link 公开提供
  • 为什么 8.8.8.8 匹配一行 8.0.0.0 ?你能解释一下吗?
  • 8.8.8.8 应该匹配 8.0.0.0,因为它已分配给此网络,0 定义范围从 0 到 255,因此 8.1.1.1 和 / 8.255.255.255 之间的所有内容都分配给 8.0.0.0

标签: linux file search awk ip-address


【解决方案1】:

awk可以用,这样:
1. 使用-F'|' 参数运行,以竖线分隔。现在$4 是第一个地址,$5 是网络大小。
2. 使用split($4,addr,'.') 得到一个数组a 有4个地址部分
3. 做一些数学运算得到数字地址:range_start=a[0]*16777216+a[1]*65536+a[2]*256+a[3].
4. 对您要查找的地址进行相同的数学运算。
5. 现在只需检查地址是否在range_start 和range_start+$5 之间的范围内

【讨论】:

  • 我正在尝试将这种方法与@shiplu 建议的方法相结合,我认为它的执行速度会快得多。
【解决方案2】:

如果第 4 列和第 5 列是 network prefix and subnet mask,则 grep 输入 ip:

#!/usr/bin/env python
import fileinput, socket, struct, sys

# x.x.x.x string -> integer
ip2int = lambda ipstr: struct.unpack('!I', socket.inet_aton(ipstr))[0]    

ip = ip2int(sys.argv.pop(1)) # get ip from command-line
for line in fileinput.input(): # read from stdin or file(s) given at command-line
    try:
        family, network_prefix, subnet_mask = line.split('|')[2:5]
        if (family == 'ipv4' and
            (ip & (2**32 - int(subnet_mask))) == ip2int(network_prefix)):
            print line,
    except Exception:
        print >>sys.stderr, "can't parse", line,

示例

$ python grep-ip.py 192.168.5.193 <<'.'
x|x|ipv4|192.168.5.128|64|x|x
x|x|ipv4|192.168.5.192|64|x|x
x|x|ipv4|192.168.5.0|64|x|x
x|x|ipv4|192.168.5.0|256|x|x
.

Output

x|x|ipv4|192.168.5.192|64|x|x
x|x|ipv4|192.168.5.0|256|x|x

【讨论】:

  • 看起来很棒,但我无法在大文件上进行测试,以便更具体地了解这个http://skechboy.com/ips/ipv4_table。我很喜欢 python,我知道这是一个非常菜鸟的问题,但是如何将输入数据设置为来自文件?
  • @SkechBoy:如果将脚本放入grep-ip 文件和chmod +x,则用法为:./grep-ip ip [FILE...] 类似 grep:搜索命名的输入文件(如果没有文件,则搜索标准输入命名,或者如果给出单个连字符减号 (-) 作为文件名)。
  • @SkechBoy:ipv4_table 中有几行不是给定格式的。我已更改脚本以忽略它们。
【解决方案3】:

这里是@ugoren方法的awk实现:

sphynx@fjord% cat ipgrep.awk

BEGIN { FS = "|"; }

{
    ip = ip2num(ADDR);
    network_start = ip2num($4);
    network_length = $5;
    if (ip >= network_start && ip <= network_start + network_length) {
        print;
    }
}

function ip2num(ip)
{
    split(ip, addr, ".");
    return addr[1] * 2^24 + addr[2] * 2^16 + addr[3] * 2^8 + addr[4];
}


sphynx@fjord% awk -v ADDR=8.8.8.8 -f ipgrep.awk data 
arin|US|ipv4|8.0.0.0|16777216|19921201|allocated

【讨论】:

  • 它比它应该匹配的更多。 gawk, mawk.
  • +1:它works。但它比Python version 慢(这很奇怪)。
  • 你应该排除右边界ip &lt; (network_start + network_length)。 9.0.0.0 不应匹配 8.0.0.0|16777216。比较awk 和#5 for python
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 2014-12-16
  • 1970-01-01
  • 2012-06-26
  • 2019-06-03
  • 1970-01-01
  • 2011-07-13
相关资源
最近更新 更多