美文网首页
网络工程师利器-textFSM使用案例

网络工程师利器-textFSM使用案例

作者: Bless_H | 来源:发表于2021-06-22 23:57 被阅读0次

    上篇文章中大致介绍了下textFSM的语法并且进行了一些简单的说明,这篇文章是一些简单的案例来帮助大家更好的理解一些特殊的用法。

测试环境
系统:windows自带ubuntu子系统

Filldown关键字用法

    下面是一段juniper设备上show chassis fpc的output,首先看下没有Filldown关键字对文本的匹配结果:

#test_parse.py
import textfsm
import os

show_chassis = '''
lcc0-re0:
--------------------------------------------------------------------------
                     Temp  CPU Utilization (%)   Memory    Utilization (%)
Slot State            (C)  Total  Interrupt      DRAM (MB) Heap     Buffer
  0  Online            24      8          1       512        16         52
  1  Online            23      7          1       256        36         53
  2  Online            23      5          1       256        36         49
  3  Online            21      7          1       256        36         49
  4  Empty
  5  Empty
  6  Empty
  7  Empty

lcc1-re1:
--------------------------------------------------------------------------
                     Temp  CPU Utilization (%)   Memory    Utilization (%)
Slot State            (C)  Total  Interrupt      DRAM (MB) Heap     Buffer
  0  Online            20      9          1       256        36         50
  1  Online            20     13          0       256        36         49
  2  Online            21      6          1       256        36         49
  3  Online            20      6          0       256        36         49
  4  Online            18      5          0       256        35         49
  5  Empty
  6  Empty
  7  Empty'''

with open('../templates/show_chassis.template') as template:
    fsm = textfsm.TextFSM(template)
    result = fsm.ParseText(show_chassis)

print(fsm.header)
for res in result:
  print(res)
#show_chassis.template

Value Chassis (\S+)
Value Slot (\d)
Value State (\w+)
Value Temperature (\d+)
Value DRAM (\d+)
Value Buffer (\d+)

Start
  ^${Chassis}:
  ^\s+${Slot}\s+${State}\s+${Temperature}\s+\d+\s+\d+\s+${DRAM}\s+\d+\s+${Buffer} -> Record
  ^\s+${Slot}\s+${State} -> Record
#输出:
['Chassis', 'Slot', 'State', 'Temperature', 'DRAM', 'Buffer']
['lcc0-re0', '0', 'Online', '24', '512', '52']
['', '1', 'Online', '23', '256', '53']
['', '2', 'Online', '23', '256', '49']
['', '3', 'Online', '21', '256', '49']
['', '4', 'Empty', '', '', '']
['', '5', 'Empty', '', '', '']
['', '6', 'Empty', '', '', '']
['', '7', 'Empty', '', '', '']
['lcc1-re1', '0', 'Online', '20', '256', '50']
['', '1', 'Online', '20', '256', '49']
['', '2', 'Online', '21', '256', '49']
['', '3', 'Online', '20', '256', '49']
['', '4', 'Online', '18', '256', '49']
['', '5', 'Empty', '', '', '']
['', '6', 'Empty', '', '', '']
['', '7', 'Empty', '', '', '']

    很明显这个输出不是我们想要的结果,我们希望每行都可以标识出chassis number。下面我们加上Filldown关键字再看下输出的结果。在Chassis这个变量中我们加上option选项中的Filldown,顾名思义向下填充。

#show_chassis.template
Value Filldown Chassis (\S+)
Value Slot (\d)
Value State (\w+)
Value Temperature (\d+)
Value DRAM (\d+)
Value Buffer (\d+)

Start
  ^${Chassis}:
  ^\s+${Slot}\s+${State}\s+${Temperature}\s+\d+\s+\d+\s+${DRAM}\s+\d+\s+${Buffer} -> Record
  ^\s+${Slot}\s+${State} -> Record
#输出
['Chassis', 'Slot', 'State', 'Temperature', 'DRAM', 'Buffer']
['lcc0-re0', '0', 'Online', '24', '512', '52']
['lcc0-re0', '1', 'Online', '23', '256', '53']
['lcc0-re0', '2', 'Online', '23', '256', '49']
['lcc0-re0', '3', 'Online', '21', '256', '49']
['lcc0-re0', '4', 'Empty', '', '', '']
['lcc0-re0', '5', 'Empty', '', '', '']
['lcc0-re0', '6', 'Empty', '', '', '']
['lcc0-re0', '7', 'Empty', '', '', '']
['lcc1-re1', '0', 'Online', '20', '256', '50']
['lcc1-re1', '1', 'Online', '20', '256', '49']
['lcc1-re1', '2', 'Online', '21', '256', '49']
['lcc1-re1', '3', 'Online', '20', '256', '49']
['lcc1-re1', '4', 'Online', '18', '256', '49']
['lcc1-re1', '5', 'Empty', '', '', '']
['lcc1-re1', '6', 'Empty', '', '', '']
['lcc1-re1', '7', 'Empty', '', '', '']
['lcc1-re1', '', '', '', '', '']

    这里的输出和我们的期望值就很近了,但是多出来了奇怪的一行。可以通过Required关键字来进行优化。

Required关键字用法

    Required表示必须的,就是本行除了Filldown变量意外,添加Required关键字的值必须匹配到值才可以返回结果。下面我在Slot和State前加上Required再看下输出结果。如下的结果就非常符合我们的预期了。

#show_chassis.template
Value Filldown Chassis (\S+)
Value Required Slot (\d)
Value Required State (\w+)
Value Temperature (\d+)
Value DRAM (\d+)
Value Buffer (\d+)

Start
  ^${Chassis}:
  ^\s+${Slot}\s+${State}\s+${Temperature}\s+\d+\s+\d+\s+${DRAM}\s+\d+\s+${Buffer} -> Record
  ^\s+${Slot}\s+${State} -> Record
['Chassis', 'Slot', 'State', 'Temperature', 'DRAM', 'Buffer']
['lcc0-re0', '0', 'Online', '24', '512', '52']
['lcc0-re0', '1', 'Online', '23', '256', '53']
['lcc0-re0', '2', 'Online', '23', '256', '49']
['lcc0-re0', '3', 'Online', '21', '256', '49']
['lcc0-re0', '4', 'Empty', '', '', '']
['lcc0-re0', '5', 'Empty', '', '', '']
['lcc0-re0', '6', 'Empty', '', '', '']
['lcc0-re0', '7', 'Empty', '', '', '']
['lcc1-re1', '0', 'Online', '20', '256', '50']
['lcc1-re1', '1', 'Online', '20', '256', '49']
['lcc1-re1', '2', 'Online', '21', '256', '49']
['lcc1-re1', '3', 'Online', '20', '256', '49']
['lcc1-re1', '4', 'Online', '18', '256', '49']
['lcc1-re1', '5', 'Empty', '', '', '']
['lcc1-re1', '6', 'Empty', '', '', '']
['lcc1-re1', '7', 'Empty', '', '', '']

List关键字

    List关键字可以将某一列定义为一个列表,将返回的多个值存储在列表中。看下面的例子来替换List关键字和Continue关键字的作用。

#test_parse.py
import textfsm
import os


route_list = '''
       Destination        Gateway                      Dist/Metric Last Change
       -----------        -------                      ----------- -----------
  B EX 0.0.0.0/0          via 192.0.2.73                  20/100        4w0d
                          via 192.0.2.201
                          via 192.0.2.202
                          via 192.0.2.74
  B IN 192.0.2.76/30     via 203.0.113.183                200/100        4w2d
  B IN 192.0.2.204/30    via 203.0.113.183                200/100        4w2d
  B IN 192.0.2.80/30     via 203.0.113.183                200/100        4w2d
  B IN 192.0.2.208/30    via 203.0.113.183                200/100        4w2d
'''


with open('../templates/route_list.template') as template:
    fsm = textfsm.TextFSM(template)
    result = fsm.ParseText(route_list)

print(fsm.header)
for res in result:
  print(res)
#route_list.template
Value Protocol (\S)
Value Type (\S\S)
Value Required Prefix (\S+)
Value Gateway (\S+)
Value Distance (\d+)
Value Metric (\d+)
Value LastChange (\S+)

Start
  ^.*----- -> Routes

Routes
  ^  ${Protocol} ${Type} ${Prefix}\s+via ${Gateway}\s+${Distance}/${Metric}\s+${LastChange} -> Record
#输出:
['Protocol', 'Type', 'Prefix', 'Gateway', 'Distance', 'Metric', 'LastChange']
['B', 'EX', '0.0.0.0/0', '192.0.2.73', '20', '100', '4w0d']
['B', 'IN', '192.0.2.76/30', '203.0.113.183', '200', '100', '4w2d']
['B', 'IN', '192.0.2.204/30', '203.0.113.183', '200', '100', '4w2d']
['B', 'IN', '192.0.2.80/30', '203.0.113.183', '200', '100', '4w2d']
['B', 'IN', '192.0.2.208/30', '203.0.113.183', '200', '100', '4w2d']

    这个输出的结果明显不是我们的预期的,缺省路由的下一跳值匹配到了一个。现在 我们再对template文件做下改动,加上List和Continue关键字。List关键字很好理解就是将Gateway这一列声明为List格式。我们再看下Continue的文档说明,保留当前行并且不再重新匹配State的第一个规则,继续运行规则好像匹配没有发生。


image.png
Value Protocol (\S)
Value Type (\S\S)
Value Prefix (\S+)
Value List Gateway (\S+)
Value Distance (\d+)
Value Metric (\d+)
Value LastChange (\S+)

Start
  ^.*----- -> Routes


Routes
  ^  \S \S\S -> Continue.Record
  ^  ${Protocol} ${Type} ${Prefix}\s+via ${Gateway}\s+${Distance}/${Metric}\s+${LastChange}
  ^\s+via ${Gateway}

    Continue这行的 \S \S\S匹配到第一行时,此时触发Continue机制,后续文本继续向下匹配并进行记录,直到出现下一个可以匹配到 \S \S\S再开始进行下一个Record。

  B EX 0.0.0.0/0          via 192.0.2.73                  20/100        4w0d

    最后的执行结果

['Protocol', 'Type', 'Prefix', 'Gateway', 'Distance', 'Metric', 'LastChange']
['B', 'EX', '0.0.0.0/0', ['192.0.2.73', '192.0.2.201', '192.0.2.202', '192.0.2.74'], '20', '100', '4w0d']
['B', 'IN', '192.0.2.76/30', ['203.0.113.183'], '200', '100', '4w2d']
['B', 'IN', '192.0.2.204/30', ['203.0.113.183'], '200', '100', '4w2d']
['B', 'IN', '192.0.2.80/30', ['203.0.113.183'], '200', '100', '4w2d']
['B', 'IN', '192.0.2.208/30', ['203.0.113.183'], '200', '100', '4w2d']

    还有一个很好的案例大家也可以看下,题主自己解决的问题,不过很实用的一个场景。
https://www.pythonheidong.com/blog/article/509484/7a82ca483a323b79066d/
还有一个很好的正则表达式练习的网站:https://regex101.com/

参考文档

textFSM官方文档
https://github.com/google/textfsm/wiki/Code-Lab

相关文章

网友评论

      本文标题:网络工程师利器-textFSM使用案例

      本文链接:https://www.haomeiwen.com/subject/vsxvyltx.html