Google开源库Textfsm使用文档(中文翻译)
TextFSM
介绍
TextFSM 是一个 Python 模块,实现了一个基于状态机的模板,用来解析半格式化的文本。
最初开发的目的是允许程序化地获取来源于 CLI 驱动设备的输出信息,例如网络路由器或交换机,不过它可以被用作任何这种类型的文本输出。
这个引擎需要两个输入:一个模板文件和文本输入(比如 CLI 设备的命令回显),并返回一个表,其中记录了从文本中解析出的数据。
每个独特结构的文本输入都需要一个模板文件。本文提供了一些代码示例,并鼓励用户独立开发。
通过开发一个模板文件池,脚本可以调用 TextFSM 从各种来源中解析出有用的信息。它同样有可能在相同的数据上用不同的模板,来制造出不同的表格(或视图)。
详细说明
使用库
快速入门示例:
# 通过 FSM 运行文本
# 这个'template'参数是一个文件对象,'raw_text_data'参数是一个字符串
re_table = textfsm.TextFSM(template)
data = re_table.ParseText(raw_text_data)
# 以 CSV 的形式来展示结果
# 打印第一列的标题
print( ', '.join(re_table.header) )
# 打印表的每一行数据
for row in data:
print( ', '.join(row) )
这个库可以通过上面的方式执行,也可以直接执行,用于检查模板语法,并将预计的输出和输入相比较:
parser.py [--help] template [input_file [output_file]]
如果安装为软件包,它将会在 Python 的相关版本文件夹下:
usr/local/lib/pythonx.y/dist-packages/textfsm/parser.py
数据形式
FSM 的核心目的是从文本数据中提取关键的数据,并将其放入一个表格形式中。
下面给出一个原始输入数据,我们也许会对线卡状态和温度感兴趣:
Routing Engine status:
Slot 0:
Current state Master
Election priority Master (default)
Temperature 39 degrees C / 102 degrees F
CPU temperature 55 degrees C / 131 degrees F
DRAM 2048 MB
Memory utilization 76 percent
CPU utilization:
User 95 percent
Background 0 percent
Kernel 4 percent
Interrupt 1 percent
Idle 0 percent
Model RE-4.0
Serial ID xxxxxxxxxxxx
Start time 2008-04-10 20:32:25 PDT
Uptime 180 days, 22 hours, 45 minutes, 20 seconds
Load averages: 1 minute 5 minute 15 minute
0.96 1.03 1.03
Routing Engine status:
Slot 1:
Current state Backup
Election priority Backup
Temperature 30 degrees C / 86 degrees F
CPU temperature 31 degrees C / 87 degrees F
DRAM 2048 MB
Memory utilization 14 percent
CPU utilization:
User 0 percent
Background 0 percent
Kernel 0 percent
Interrupt 1 percent
Idle 99 percent
Model RE-4.0
Serial ID xxxxxxxxxxxx
Start time 2008-01-22 07:32:10 PST
Uptime 260 days, 10 hours, 45 minutes, 39 seconds
使用一个恰当的模板将此文本输入应用于 FSM,结果返回一个表格形式,其中线卡和相关数据作为记录的字段关联在一起。
Slot | 型号 | 内存 | 状态 | 温度 | CPU温度 |
---|---|---|---|---|---|
0 | RE-4.0 | 2048 | Master | 39 | 55 |
1 | RE-4.0 | 2048 | Backup | 30 | 31 |
模板文件
模板文件描述了 FSM 应当如何解析数据,不同的文本输入形式需要单独的模板。比如,解析路由器命令的输出,通常每一个命令都需要一个模板。
下面是一个完整的模板示例。在这个示例中,展示了如何处理路由器上的 'show chassis routing-engine' 命令的输出:
# # Chassis value will be null for single chassis routers.
Value Filldown Chassis (.cc.?-re.)
Value Required Slot (\d+)
Value State (\w+)
Value Temp (\d+)
Value CPUTemp (\d+)
Value DRAM (\d+)
Value Model (\S+)
# FSM 总是先在'start'状态启动
Start
^${Chassis}
# Record current values and change state.
# No record will be output on first pass as 'Slot' is 'Required' but empty.
^Routing Engine status: -> Record RESlot
# 状态转换是非必须的,但是这有助于示例
RESlot
^\s+Slot\s+${Slot}
^\s+Current state\s+${State}
^\s+Temperature\s+${Temp} degrees
^\s+CPU temperature\s+${CPUTemp} degrees
^\s+DRAM\s+${DRAM} MB
# Transition back to Start state.
^\s+Model\s+${Model} -> Start
# 一个隐式的 EOF 状态输出,会执行最后一次记录
模板文件由两个顶级部分组成
-
Value 的定义,描述了要提取的数据列;
-
一个或更多的状态的定义,描述了解析数据时引擎的多种状态。
如果一行以任意数量的空格开头再跟一个井号(即与正则表达式^\s*#
匹配),则被认为是一个注释。
Value 定义
一行或多行的 Value 被用作描述每一个列,并且它将会出现在作为结果的表格中。所有的 Value 必须出现在状态定义之前,并且行之间必须相邻(除了被注释分隔)。
每行 Value 都是下面这种格式:
Value [option[,option...]] name regex
关键字 | 类型 | 描述 |
---|---|---|
Value | 关键字 | 表示开始定义Value ,必填项。 |
option | 标志位。逗号分隔,不能有空格 | 关于Value 的额外选项。可以是以下一项或多项:Filldown 先前匹配的值会保留到之后的记录(除非显式清除或再次匹配)。换句话说, 最近的匹配值会被复制到新的行,除非再次匹配。 Key 宣告字段的内容作为行的唯一标识符。 Required 仅当此值匹配时,记录(行)才会保存到表中。 List 表示这个值是一个列表,增加到每一次匹配(否则通常来说每次匹配都将覆写那一个行的值)。 Fillup 类似 Filldown ,但是向上填充,直到它找到一个非空的记录。不能与Required 或List 兼容。 |
name | 名称 | 用于Value 的命名, 最终将作为列名。不能用已存在的option 的名称来命名。 |
regex | 正则表达式 | 一个正则表达式,用于匹配Value ,这个正则表达式必须包含在括号中。 |
状态定义
在 Value 定义之后,开始描述状态定义。每个状态定义之间要用一个空行分开。第一行是一个由字母或数字组成的状态名,随后是一连串的 rule(规则)。
一个完整的状态定义是下面这种格式:
StateName
^rule
^rule
...
多行状态定义之间至少用一个空行分开。多个规则要写在连续的行上(不能有空行),并紧跟在状态名之后,且规则前面必须用一个或两个空格缩进,加上一个插入符号^
来开头。
启动的时候,FSM 将开始于 Start 状态。输入行仅能和当前状态的规则相比较,但是一个匹配的输入行可以触发一个状态转换,来转换到新的状态。
操作会逐行继续,直到遇到 EOF 状态或当前状态转换到 End 状态。
保留状态
FSM 开始于 Start 状态,所以这个标签是强制的,模板失去它将不能解析。
如果输入达到了 EOF 状态,那么 EOF 状态将会执行。这是一个隐式的状态,看起来像是这样:
EOF
^.* -> Record
EOF 在返回之前记录当前行,可以去覆盖这个行为:显式定义一个空的 EOF 状态,像是这样:
EOF
End 状态是保留状态,并会终止输入行的进程,且不执行 EOF 状态。
状态规则
每个状态定义由一个或多个的规则组成。FSM 从输入缓冲区读取一行,依次对照每个规则进行检测(从当前状态的第一条规则开始)。如果一个规则匹配了这行内容,那么 action(行为) 会执行,并重复进程(从第一个状态开始)。
规则是下面这种格式:
^regex [-> action]
regex 是一个正则表达式,用于和输入行相匹配。这个匹配会从输入行的开头执行,所以尽管插入符号(^)是隐式的,但需要在语法上显式指定,以提醒此行为。
正则表达式中可能包含零个或更多的 Value 描述符。Value 描述符采用这两种格式 $ValueName 或 ${ValueName}(推荐后者的格式),表示从 Value 中取值。关联 Value 的正则表达式会被替换到规则的正则表达式中,并且如果输入行匹配了规则,与 Value 匹配的文本会赋值给当前记录。
指定行的结束(EOL)需要使用两个美元符号$$
,当 Value 替换的时候将被替换为一个美元符号。
比如采用下面这个模板:
Value Interface (\S+)
Start
^Interface ${Interface} is up
当开始解析这个模板的时候,FSM 会扩展规则的正则表达式为:
^Interface (\S+) is up
如果通过这个规则解析下面的输入行,这个Interface
的值会被赋予一个值:GigabitEthernet1/10
Interface GigabitEthernet1/10 is up.
可以将多个 Value描述符 放到一个规则的正则表达式中。但是所有额外的正则表达式必须全部匹配,才能将所有的值分配到记录。
规则行为
在正则表达式之后,可能需要描述行为。由符号->
分隔,格式是这样:'A.B C'。
行为被分解为三个可选部分:A) 行行为,在输入行上的行为。B) 记录行为,对目前为止收集到的值执行的行为。C) 状态转换。
如果没有描述行为,也就是说没有->
符号,那么默认的隐式行为是Next.NoRecord
行行为
行为 | 描述 |
---|---|
Next | 结束输入行,读取下一行并从 start 状态再次开始匹配。如果没有指定行行为,那么这会是默认行为。 |
Continue | 保持当前行,并不再从状态的第一个规则匹配。程序将继续处理规则,就好像匹配没有发生过(值的分配仍会发生)。 |
记录行为
在行行为之后是可选的记录行为,它们之间用一个英文句号分隔.
。
行为 | 描述 |
---|---|
NoRecord | 什么也不做。这是默认行为,如果没有指定记录行为。 |
Record | 将目前为止已经收集到的值作为一行记录添加到返回数据中。非 Filldown 的值会被清除。注意: 如果这里有任意未赋值的 Required 值,则记录(行)将不会被添加到返回数据中。 |
Clear | 清除非 Filldown 的值 |
Clearall | 清除所有值 |
仅当同时指定了行和记录行为时,才需要点.
分隔符。如果一个或两个行为被保留为隐式默认值,那么这个点可以忽略。例如:Next
、Next.NoRecord
、NoRecord
,它们之间是等价的。
状态转换
这个行为是可选的,在行行为或记录行为后面添加一个空格和一个新的状态名,来表示转换到新的状态。这个新的状态必须是一个保留状态或一个在模板中有效定义的状态。
匹配后,在正常执行所有行为后,从输入中读取下一行,然后将当前状态更改为新状态,并在此新状态中继续处理进程。
注意:Continue 行为不会接受状态转换。这会确保状态机是无环的。
错误行为
这里有一个特殊的行为 Error。这个行为将终结所有进程并且将不会返回到表格,丢弃到目前为止收集的所有的行,并抛出一个异常。
这个行为的语法是这样的:
^regex -> Error [word|"string"]