即时焦点:正则解析网络运维数据之OneTake 解析网络运维数据

发布时间:   来源:CSDN  

今天我们带大家写个正则表达式,解析一下我们的网络运维数据。写的时候我会分成两种风格:

one take

分而治之分别对应网络配置中的两种常见的形式。


【资料图】

今天的分享,我们先讲one take,也就是一次完成提取。【林志炫的专辑】。

网络设备配置(show 出来的,包含config和status)的解析有些是适合一次过的,比如show mac,arp,interface brief等很多信息在一行中的。我们只要写好一个正则,很多信息都可以一次获取解析出来。这种最大的特点就是一行包含一条信息。

我们登陆devnet提供的一台虚拟的N9K设备,执行命令show int brief如下

讲下我的思路,写一个正则,能提取端口信息的每个字段信息,然后把整个log用换行切割开,for循环,提取每行内的端口信息,有就追加到一个端口列表中,没有继续下一行。直到循环结束,我们就可以拿到所有端口的信息了。

下面我们开始写正则。其实从show出来的log里我们也能知道我们需提取那些字段,比如端口名,vlan,类型,模式,状态以及状态的原因,速率,所属的portchannel。我们就一一解析出来。

我们先直接上代码,然后细细讲讲

写一次正则,然后每行去正则匹配,就可以非常方便的把信息解析出来了。

这个正则看起来很复杂,可能吓跑很多同学,咱们别着急,庖丁解牛,一个个的分析,其实很容易就写出正则。

我们看到最初的配置,我们在行内从端口名称一个个找。

首先写端口的名称 是“Eth数字\数字”,我们写成正则就是Eth\d+/\d+,我们捕获这个子串,用圆括号圈起来就是“(Eth\d+/\d+)”,然后是vlan 是数字或者“--”,我们可以写成“(\d+|--)”,和端口中间是空格,为了不数空格,我们用\s+来代表多个空格,我们就接着在端口的正则后面写“(Eth\d+/\d+) \s+(\d+|--)”

我们每写一点可以执行代码,去匹配一下看看输出结果,看看能不能解析打印出来,不合适的就去调整。

正则的方式千千万万,我们可以适当的去调整它的一些特征,去尽量匹配准确一些,比如access、trunk、routed三种,将来万一再多一些,我们可以把这段用“(\w+)”去捕获,比较限定死的方式是“(access|trunk|routed)”,大家根据自己情况去写。后面就一点点加进去。

这里面有个小坑,就是reason。

端口状态的原因有可能是两个单词也可能是一个单词,这个时候我们如果用字符去匹配的话没法兼容两种情况。

所以我用的方法是“([\s\S]+?)”匹配原因,后面的在端口速率和portchannel那写死,中间用贪婪匹配所有的状态和速率之间的字符或者空格,这样就提取除了reason 这个字段。

写的过程中,我是一次写完正则,但是没过,后来我从后面去除一些正则,加一个,打印正确就再加一个再试试。这个方法大家可以去尝试,一次过,真的很不容易。

这个特别适合写mac arp 端口(brief)一行的情况解析。

我们再来练习一个arp地址解析吧。

arp的特征非常明显,IP地址,存活时间,mac地址和端口

开启第一视角,先去匹配IP,这个IP不是那么严谨,但是在匹配过程中足够了,注意“.”在正则里是有特殊含义的,所以需要转义。

然后陆续添加时间,我们可以用非空字符去表示,那就是(\S+)

mac地址是“([a-fA-F0-9]{4}\.[a-fA-F0-9]{4}\.[a-fA-F0-9]{4})” 这个用了严谨的写法,就是给大家更多思路。

vlan的我就不写了 大家自己动手谢谢试试吧

今天分享的讲了怎么用正则处理这种单行的解析。有些负责的我们会用分而治之的方法,比如端口的配置或者show,后续分享。

解析不是目的,数据产生是后续场景使用的基础,数据的使用才是目的。比如我们统计资源信息、做安全管理、IP地位等等。

一定要落地到场景里去,大家每次想问题也要带着场景去思考,我能用自动化做什么,这个事情能不能用自动化做等等。

补充一个知识点:分割行的时候我们用的是\n,大家根据实际情况去分割。

Linux采集下的大部分是\r\n 有时候是\\r\\n,建议大家采集回来后统一替换。

最后奉上两端代码:

我们只是打印出来,大家按实际使用去消费数据,建议封装成字典或者对象入库入表。包括“--”我没有处理成None或者其他值,都是需要大家注意的地方。

import rewith open("show_int_bri.log","r",encoding="utf8") as f:    log = f.read()    interfae_info_pattern = re.compile(r"(Eth\d+/\d+)\s+(\d+|--)\s+(\w+)\s+(\w+)\s+(\w+)\s+([\s\S]+?)\s+(\w+)\(D\)\s+(\S+)")    lines = log.split("\n")    for line in lines:        match =  interfae_info_pattern.match(line)        if match:            print(match.groups())

import rewith open("showarp.log","r",encoding="utf8") as f:    log = f.read()    arp_pattern = re.compile(r"(\d+\.\d+\.\d+\.\d+)\s+(\S+)\s+([a-fA-F0-9]{4}\.[a-fA-F0-9]{4}\.[a-fA-F0-9]{4})")    lines = log.split("\n")    for line in lines:        match =  arp_pattern.match(line)        if match:            print(match.groups())

相关文章Related

返回栏目>>