前言:
当前看官们对“pythonfsm”都比较关心,大家都想要剖析一些“pythonfsm”的相关内容。那么小编也在网摘上汇集了一些有关“pythonfsm””的相关内容,希望我们能喜欢,同学们一起来了解一下吧!弈心:从事计算机网络工作11年(新加坡7年,沙特4年),2013年考取CCIE,在新加坡先后任职于AT&T,新加坡交通部,苹果,Equinix,苏格兰皇家银行等大型企业、银行和政府部门。 目前供职于“世界第一土豪大学“沙特阿卜杜拉国王科技大学(KAUST),担任Senior Network Engineer,为KAUST校史上第一位也是唯一一位华人IT部门高级职员。2019年6月在知乎发布了华语圈第一本专门为编程零基础的网络工程师量身打造的Python教程《网络工程师的Python之路》。
在上星期发表的《网络工程师的Python之路 -- TextFSM和ntc-template》一文中,笔者介绍了如何使用TextFSM配合ntc-template提供的模板集来将不支持API的传统网络设备的show和display命令的回显内容转换成JSON阵列、列表类型的有序数据格式,方便我们对这些回显内容输出的参数和数据做解析,从而解决了文中提到的“正则表达式的痛点“。后来笔者也在《网络工程师的Python之路 --- NAPALM》一文中介绍了另外一个帮助我们解决类似问题的很好用的第三方开源Python模块:NAPALM的使用方法。
虽然ntc-template和NAPALM非常好用,但它们也有个致命的缺点:它们都是被其开发者按照自己的习惯和喜好提前造好的“轮子”,不论是ntc-template还是NAPALM,它们返回的数据的格式是统一、固定的,很难满足有个性化需求的使用者,这点我在《网络工程师的Python之路 --- NAPALM》一文中有专门提到过。正因如此,当我们对回显内容的解析有个性化需求时,笔者推荐使用TextFSM来编写自己需要的模板,今天就来介绍下如何使用TextFSM来自己造轮子,满足个性化需求,下面进入正文。
TextFSM的安装
作为Python的第三方模块,TextFSM有两种安装方法:
第一种方法是使用pip来安装:
进入Python并import textfsm,如果Python没有报错则说明安装成功。
除了pip外,我们也可以使用下面的git clone命令从GitHub下载textfsm的源代码,如果你的CentOS 8主机没有安装git,系统会提醒你一并安装。
Git clone
源代码下载完后,会看到当前目录下多出了一个textfsm文件夹,进入该文件夹后,会看到一个setup.py文件:
然后输入下面命令执行该py文件进行安装即可:
python3.8 setup.py install
TextFSM模板的创建和应用
TextFSM的语法本身并不难,但是使用者必须熟练掌握正则表达式。下面我们以一个思科Nexus 7000交换机上“show vlan”的回显内容为例,来看看如何用TextFSM创建模板,以及如何使用模板将该“show vlan”命令的回显内容整理成我们想要的数据格式:
N7K# show vlan VLAN Name Status Ports ---- -------------------------------- --------- ------------------------------- 1 default active Eth1/1, Eth1/2, Eth1/3 Eth1/5, Eth1/6, Eth1/7 2 VLAN0002 active Po100, Eth1/49, Eth1/50 3 VLAN0003 active Po100, Eth1/49, Eth1/50 4 VLAN0004 active Po100, Eth1/49, Eth1/50 5 VLAN0005 active Po100, Eth1/49, Eth1/50 6 VLAN0006 active Po100, Eth1/49, Eth1/50 7 VLAN0007 active Po100, Eth1/49, Eth1/50 8 VLAN0008 active Po100, Eth1/49, Eth1/50
这里我们创建一个TextFSM模板,模板内容如下:
Value VLAN_ID (\d+)Value NAME (\w+)Value STATUS (\w+) Start ^${VLAN_ID}\s+${NAME}\s+${STATUS}\s+ -> Record在TextFSM中,我们使用Value语句来定义变量,这里我们定义了三个变量,分别为VLAN_ID,NAME,STATUS。
Value VLAN_ID (\d+)Value NAME (\w+)Value STATUS (\w+)每个变量后面有它自己对应的正则表达式模式(pattern),这些模式写在括号()中。比如变量VLAN_ID顾名思义是要去匹配VLAN的ID号的,所以它后面的正则表达式模式写为(\d+),\d这个特殊序列用来匹配数字,后面的+用来做贪婪匹配。同理,NAME这个变量是用来匹配VLAN的名称的,因为这里VLAN的名称参杂了字母和数字,比如VLAN0002, 因此它的正则表达式模式写为(\w+),\w这个特殊序列用来匹配字母或数字,配合后面的+用来做贪婪匹配。同理,变量STATUS(\w+)用来匹配VLAN状态,VLAN状态会有active和inactive之分。
在定义好变量后,我们使用Start语句来定义匹配规则,匹配规则由正则表达式的模式以及我们的变量名组成:
Start ^${VLAN_ID}\s+${NAME}\s+${STATUS}\s+ -> RecordStart语句后面必须以正则表达式^开头,^是正则表达式中的一种特殊字符,它用于匹配输入字符串的开始位置,注意紧随其后的$不是正则表达式里的$,它的作用并不是用来匹配输入字符串的结尾位置。而是用来调用我们之前设置好的VLAN_ID并匹配该变量(注意在TextFSM中调用变量的时候可以用大括号{},写成${VLAN_ID},也可以不调用,写成$VLAN_ID,但是TextFSM官方推荐使用大括号),而VLAN_ID对应的正则表达式恰巧是\d+,这样就匹配到了1,2,3,4,5,6,7,8这些VLAN ID,而后面的\s+$则表示匹配1,2,3,4,5,6,7,8后面的空格字符(\s这个特殊序列用来匹配空格字符)
^${VLAN_ID}\s+同理,我们这里调用变量NAME,它对应的正则表达式模式为\w+,该特殊序列用来匹配“show vlan”命令回显内容中的default,VLAN0002,VLAN0003….VLAN0008等内容,而后面的\s+$则用来匹配之后所有空格字符:
${NAME}\s+变量{STATUS}也一样,它对应的\w+用来匹配“active”和“inactive”这两种VLAN状态(例子中给出的show vlan的回显内容中没有“inactive”,但是不影响理解)以及后面的空格字符。最后我们用-> Record来结束TextFSM的匹配规则。
${STATUS}\s+ -> Record
在了解了TextFSM的语法基础后,接下来我们来看怎么在Python中使用TextFSM。首先将上面的TextFSM模板文件以文件名“show_vlan.template”保存:
然后在相同的文件夹下创建一个名叫textfsm_demo.py的Python脚本:
将下面的代码写入该脚本:
from textfsm import TextFSM output = ''' N7K# show vlan VLAN Name Status Ports ---- -------------------------------- --------- ------------------------------- 1 default active Eth1/1, Eth1/2, Eth1/3 Eth1/5, Eth1/6, Eth1/7 2 VLAN0002 active Po100, Eth1/49, Eth1/50 3 VLAN0003 active Po100, Eth1/49, Eth1/50 4 VLAN0004 active Po100, Eth1/49, Eth1/50 5 VLAN0005 active Po100, Eth1/49, Eth1/50 6 VLAN0006 active Po100, Eth1/49, Eth1/50 7 VLAN0007 active Po100, Eth1/49, Eth1/50 8 VLAN0008 active Po100, Eth1/49, Eth1/50 ''' f = open('show_vlan.template') template = TextFSM(f) print (template.ParseText(output))
代码分段讲解
首先我们用from textfsm import TextFSM引入textfsm模块的TextFSM函数, 该函数为textfsm模块下最核心的函数。
from textfsm import TextFSM将show_vlan的回显内容以三引号字符串的形式赋值给output这个变量:
output = ''' N7K# show vlan VLAN Name Status Ports ---- -------------------------------- --------- ------------------------------- 1 default active Eth1/1, Eth1/2, Eth1/3 Eth1/5, Eth1/6, Eth1/7 2 VLAN0002 active Po100, Eth1/49, Eth1/50 3 VLAN0003 active Po100, Eth1/49, Eth1/50 4 VLAN0004 active Po100, Eth1/49, Eth1/50 5 VLAN0005 active Po100, Eth1/49, Eth1/50 6 VLAN0006 active Po100, Eth1/49, Eth1/50 7 VLAN0007 active Po100, Eth1/49, Eth1/50 8 VLAN0008 active Po100, Eth1/49, Eth1/50 '''打开之前创建好的模板文件show_vlan.template, 调用TextFSM()函数将它赋值给template这个变量,最后调用template下的ParseText()函数对文本内容做解析,ParseText()函数里的参数output即为show vlan命令的回显内容,最后我们用print命令来看看被模板解析后的回显内容是什么样的:
f = open('show_vlan.template') template = TextFSM(f) print (template.ParseText(output))
一切就绪后,我们来执行脚本看效果:
可以看到,之前无序的纯字符串文本内容在被我们创建的TextFSM模板解析后,已经被有序的嵌套列表替代,方便我们配合for循环做很多事情。如果你觉得输出结果不易读,也可以自己导入json来将它转化成JSON阵列,方法请参考《网络工程师的Python之路 -- TextFSM和ntc-template》一文。
标签: #pythonfsm