从 ifconfig (ubuntu) 中提取网络信息的算法 [英] Algorithm to extract network info from ifconfig (ubuntu)

查看:59
本文介绍了从 ifconfig (ubuntu) 中提取网络信息的算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从 ifconfig (ubuntu) 解析信息.通常,我会将这样的一大块数据拆分为单词,然后搜索子字符串以获得我想要的.例如,给定 line = "inet addr:192.168.98.157 Bcast:192.168.98.255 Mask:255.255.255.0",并查找广播地址,我会这样做:

 for word in line.split():如果 word.startswith('Bcast'):打印 word.split(':')[-1]>>>192.168.98.255

然而,我觉得是时候开始学习如何使用正则表达式来完成这样的任务了.到目前为止,这是我的代码.我已经破解了几种模式(inet addr、Bcast、Mask).代码后的问题...

# git clone git://gist.github.com/1586034.git gist-1586034进口重新导入jsonifconfig = """;eth0 链接封装:以太网 HWaddr 08:00:27:3a:ab:47inet 地址:192.168.98.157 广播:192.168.98.255 掩码:255.255.255.0inet6 地址:fe80::a00:27ff:fe3a:ab47/64 范围:链接上行广播运行多播 MTU:1500 公制:1RX 数据包:189059 错误:0 丢弃:0 溢出:0 帧:0TX 数据包:104380 错误:0 丢弃:0 溢出:0 载波:0碰撞:0 txqueuelen:1000RX 字节:74213981 (74.2 MB) TX 字节:15350131 (15.3 MB)\n\nlo 链路封装:本地环回inet 地址:127.0.0.1 掩码:255.0.0.0inet6 地址:::1/128 范围:主机上环回运行 MTU:16436 公制:1RX 数据包:389611 错误:0 丢弃:0 溢出:0 帧:0TX 数据包:389611 错误:0 丢弃:0 溢出:0 载波:0碰撞:0 txqueuelen:0RX 字节:81962238 (81.9 MB) TX 字节:81962238 (81.9 MB)"对于 ifconfig.split('\n\n') 中的段落:信息 = {'eth_port': '','IP地址': '','广播地址':'','MAC地址': '','网络掩码':'','向上':错误,'运行':错误,'广播':错误,'多播':假,}如果段落中的广播":信息['广播'] = 真如果多播"在段落中:info['multicast'] = True如果段落中的UP":info['up'] = True如果段落中的正在运行":信息['正在运行'] = 真ip = re.search( r'inet addr:[^\s]+', 段落 )如果 ip:info['ip_address'] = ip.group().split(':')[-1]bcast = re.search( r'Bcast:[^\s]+', 段落 )如果广播:info['broadcast_address'] = bcast.group().split(':')[-1]mask = re.search( r'Mask:[^\s]+', 段落 )如果掩码:info['net_mask'] = mask.group().split(':')[-1]打印段落打印 json.dumps(info, indent=4)

这是我的问题:

  1. 对于已经实施的模式,我是否采用了最佳方法?我可以在不拆分 ':' 然后选择数组的最后一个的情况下获取地址吗?

  2. 我一直在使用 HWaddr.匹配此 mac 地址的模式是什么?

好的,这就是我最终的处理方式.我开始尝试在没有正则表达式的情况下解决这个问题……只是操纵刺痛和列表.但事实证明这是一场噩梦.例如,将 HWaddr 与其地址分开的是一个 space.现在将 inet addr 与它的地址用 : 分开.像这样用不同的分离器刮擦是一个棘手的问题.不仅编码有问题,阅读也有问题.

所以,我用正则表达式做到了这一点.我认为这为何时使用正则表达式提供了强有力的理由.

# git clone git://gist.github.com/1586034.git gist-1586034# 用法:将 ifconfig 管道化到脚本中.即ifconfig |python pyifconfig.py"# 输出是一个json数据结构列表导入系统进口重新导入jsonifconfig = sys.stdin.read()打印开始输入"打印 ifconfig打印'ENDINPUT'定义提取(输入):mo = re.search(r'^(?Peth\d+|eth\d+:\d+)\s+' +r'链接封装:(?P\S+)\s+' +r'(HWaddr\s+(?P\S+))?'+r'(\s+inet addr:(?P\S+))?'+r'(\s+Bcast:(?P\S+)\s+)?'+r'(掩码:(?P\S+)\s+)?',输入,re.MULTILINE )如果莫:info = mo.groupdict('')信息['正在运行'] = False信息['up'] = False信息['多播'] = False信息['广播'] = False如果输入中为正在运行":信息['正在运行'] = 真如果输入中为UP":info['up'] = True如果输入中为广播":信息['广播'] = 真如果输入中为MULTICAST":info['multicast'] = True返回信息返回 {}interfaces = [extract(interface) for interface in ifconfig.split('\n\n') if interface.strip() ]打印 json.dumps(interfaces, indent=4)

解决方案

对于已经实施的模式,我是否采用了最佳方法?我可以在不拆分 ':' 然后选择数组的最后一个的情况下获取地址吗?

虽然[^\s] 等价于 \S,但你的模式很适合他们正在做的事情.

您可以通过将地址放入捕获组来获取地址而无需在:"上拆分,如下所示:

 ip = re.search(r'inet addr:(\S+)', 段落)如果 ip:info['ip_address'] = ip.group(1)

如果您有更多的正则表达式分组部分,您可以按照它们在正则表达式中出现的顺序(从 1 开始)来引用它们.

<块引用>

我一直在使用 HWaddr.匹配此 mac 地址的模式是什么?

现在你知道了分组,你可以像其他地址一样获取 HWaddr:

 mac = re.search(r'HWaddr\s+(\S+)', 段落)如果 mac:info['mac_address'] = mac.group(1)

请注意,使用更高级的正则表达式,您实际上可以同时执行多个步骤.例如这里是一个示例正则表达式,它一步拉出接口名称、IP 地址和网络掩码:

<预><代码>>>>re.findall(r'^(\S+).*?inet addr:(\S+).*?Mask:(\S+)', ifconfig, re.S | re.M)[('eth0', '192.168.98.157', '255.255.255.0'), ('lo', '127.0.0.1', '255.0.0.0')]

Im trying to parse info from ifconfig (ubuntu). Normally, I would split a chunk of data like this down into words, and then search for substrings to get what I want. For example, given line = "inet addr:192.168.98.157 Bcast:192.168.98.255 Mask:255.255.255.0", and looking for the broadcast address, I would do:

for word in line.split():
    if word.startswith('Bcast'):
        print word.split(':')[-1]

>>>192.168.98.255

However, I feel its about time to start learning how to use regular expressions for tasks like this. Here is my code so far. I've hacked through a couple of patterns (inet addr, Bcast, Mask). Questions after code...

# git clone git://gist.github.com/1586034.git gist-1586034
import re
import json

ifconfig = """
eth0      Link encap:Ethernet  HWaddr 08:00:27:3a:ab:47  
          inet addr:192.168.98.157  Bcast:192.168.98.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe3a:ab47/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:189059 errors:0 dropped:0 overruns:0 frame:0
          TX packets:104380 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:74213981 (74.2 MB)  TX bytes:15350131 (15.3 MB)\n\n
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:389611 errors:0 dropped:0 overruns:0 frame:0
          TX packets:389611 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:81962238 (81.9 MB)  TX bytes:81962238 (81.9 MB)
"""

for paragraph in ifconfig.split('\n\n'):
        
    info = {
        'eth_port': '',
        'ip_address': '',
        'broadcast_address': '',
        'mac_address': '',
        'net_mask': '',
        'up': False,
        'running': False,
        'broadcast': False,
        'multicast': False,
    }
    
    if 'BROADCAST' in paragraph:
        info['broadcast'] = True
        
    if 'MULTICAST' in paragraph:
        info['multicast'] = True
        
    if 'UP' in paragraph:
        info['up'] = True
        
    if 'RUNNING' in paragraph:
        info['running'] = True
        
    ip = re.search( r'inet addr:[^\s]+', paragraph )
    if ip:
        info['ip_address'] = ip.group().split(':')[-1]  
    
    bcast = re.search( r'Bcast:[^\s]+', paragraph )
    if bcast:
        info['broadcast_address'] = bcast.group().split(':')[-1]
    
    mask = re.search( r'Mask:[^\s]+', paragraph )
    if mask:
        info['net_mask'] = mask.group().split(':')[-1]

    print paragraph
    print json.dumps(info, indent=4)

Here're my questions:

  1. Am I taking the best approach for the patterns I have already implemented? Can I grab the addresses without splitting on ':' and then choosing the last of the array.?

  2. I'm stuck on HWaddr. What would be a pattern to match this mac address?

EDIT:

Ok, so here's how I ended up going about this. I started out trying to go about this without the regex... just manipulating stings and lists. But that proved to be a nightmare. For example, what separates HWaddr from its address is a space. Now take inet addr its separated from its address by :. Its a tough problem to scrape with differing separators like this. Not only a problem to code but also a problem to read.

So, I did this with regex. I think this makes a strong case for when to use regular expressions.

# git clone git://gist.github.com/1586034.git gist-1586034

# USAGE: pipe ifconfig into script. ie "ifconfig | python pyifconfig.py"
# output is a list of json datastructures

import sys
import re
import json

ifconfig = sys.stdin.read()

print 'STARTINPUT'
print ifconfig
print 'ENDINPUT'

def extract(input):
    mo = re.search(r'^(?P<interface>eth\d+|eth\d+:\d+)\s+' +
                     r'Link encap:(?P<link_encap>\S+)\s+' +
                     r'(HWaddr\s+(?P<hardware_address>\S+))?' +
                     r'(\s+inet addr:(?P<ip_address>\S+))?' +
                     r'(\s+Bcast:(?P<broadcast_address>\S+)\s+)?' +
                     r'(Mask:(?P<net_mask>\S+)\s+)?',
                     input, re.MULTILINE )
    if mo:
        info = mo.groupdict('')
        info['running'] = False
        info['up'] = False
        info['multicast'] = False
        info['broadcast'] = False
        if 'RUNNING' in input:
            info['running'] = True
        if 'UP' in input:
            info['up'] = True
        if 'BROADCAST' in input:
            info['broadcast'] = True
        if 'MULTICAST' in input:
            info['multicast'] = True
        return info
    return {}


interfaces = [ extract(interface) for interface in ifconfig.split('\n\n') if interface.strip() ]
print json.dumps(interfaces, indent=4)

解决方案

Am I taking the best approach for the patterns I have already implemented? Can I grab the addresses without splitting on ':' and then choosing the last of the array.?

Your patterns are fine for what they are doing, although [^\s] is equivalent to \S.

You can grab the addresses without splitting on ':' by putting the address into a capturing group, like this:

    ip = re.search(r'inet addr:(\S+)', paragraph)
    if ip:
        info['ip_address'] = ip.group(1)

If you had more grouped portions of the regex you could refer to them by the order they appear in your regex, starting at 1.

I'm stuck on HWaddr. What would be a pattern to match this mac address?

Now that you know about grouping, you can get HWaddr the same way as the other addresses:

    mac = re.search(r'HWaddr\s+(\S+)', paragraph)
    if mac:
        info['mac_address'] = mac.group(1)

Note that with a more advanced regular expression you could actually do several of these steps all at once. For example here is an example regex that pulls out the interface name, ip address, and net mask in one step:

>>> re.findall(r'^(\S+).*?inet addr:(\S+).*?Mask:(\S+)', ifconfig, re.S | re.M)
[('eth0', '192.168.98.157', '255.255.255.0'), ('lo', '127.0.0.1', '255.0.0.0')]

这篇关于从 ifconfig (ubuntu) 中提取网络信息的算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆