有没有办法用 TextFSM 一次记录多行?
Is there a way to record multiple lines at once with TextFSM?
我想解析通过 Netmiko 使用 TextFSM 执行的检查点防火墙 cphaprob -a if
。最终生成的列表格式不正确。
我已经尝试了很多 TextFSM 命令组合,但也许我只是不明白它是如何正常工作的。
原始命令输出
下面是 cphaprob -a if
原始输出。我想解析虚拟上下文(例如 'vcont 0')、接口名称(例如 'bond0')、虚拟接口(例如 'bond0.2121')及其主机名(例如“10.105.0.42”)。
vcont 0:
------
Required interfaces: 2
Required secured interfaces: 1
eth0 UP non sync(non secured), multicast
eth1 UP sync(secured), broadcast
Virtual cluster interfaces: 1
eth0 10.105.0.42
vcont 1:
------
Required interfaces: 3
Required secured interfaces: 1
eth1 UP sync(secured), broadcast
bond0 UP non sync(non secured), multicast, bond Load Sharing (bond0.2101)
bond1 UP non sync(non secured), multicast, bond Load Sharing (bond1.2126)
Virtual cluster interfaces: 3
bond0.2121 10.65.29.21
bond1.2122 10.65.29.22
bond1.2123 10.65.29.23
vcont 2:
------
Required interfaces: 3
Required secured interfaces: 1
eth1 UP sync(secured), broadcast
bond1 UP non sync(non secured), multicast, bond Load Sharing (bond1.2127)
bond0 UP non sync(non secured), multicast, bond Load Sharing (bond0.2102)
Virtual cluster interfaces: 2
bond1.4242 10.65.29.42
bond0.4243 10.65.29.43
TextFSM 模板
# template for ```cphaprob -a if``` command.
Value Context (\S+\s\d+)
Value List Interface (\S+)
Value List VirtualInterface (\S+)
Value List IPv4 (\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})
Start
^${Context}:
^${Interface}.*(UP|DOWN|Disconnected)
^Virtual cluster interfaces: \d+ -> Cluster
Cluster
^${VirtualInterface}\s+${IPv4} -> Record Start
预期结果
$ python tests/test_checkpoint_functions.py
[['vcont 0', ['eth0', 'eth1'], ['eth0'], ['10.105.0.42']],
['vcont 1', ['eth1', 'bond0', 'bond1'], ['bond0.2121', 'bond1.2122', 'bond1.2123'], ['10.65.29.21', '10.65.29.22', '10.65.29.23']],
['vcont 2', ['eth1', 'bond1', 'bond0'], ['bond1.4242', 'bond0.4243'], ['10.65.29.42', '10.65.29.43']]]
实际结果
$ python tests/test_checkpoint_functions.py
[['vcont 0', ['eth0', 'eth1'], ['eth0'], ['10.105.0.42']],
['vcont 1', ['eth1', 'bond0', 'bond1'], ['bond0.2121'], ['10.65.29.21']],
['vcont 2', ['eth1', 'bond1', 'bond0'], ['bond1.4242'], ['10.65.29.42']]]
如您所见,我只获得了第一次出现的虚拟接口及其对应的 IP 地址。原因可能是我在 Cluster 状态的模板中,我在 ^${VirtualInterface}\s+${IPv4} -> Record Start
之后记录。我只是不知道如何在相应列表中获取所有虚拟接口和 IP 地址。
Value Context (\S+\s\d+)
Value List Interface (\S+)
Value List VirtualInterface (\S+)
# Add escaping for "."
Value List IPv4 (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})
Start
^${Context}:
^${Interface}.*(UP|DOWN|Disconnected)
^Virtual cluster interfaces: \d+ -> Cluster
Cluster
^${VirtualInterface}\s+${IPv4}
# The reason for the multiple VirtualInterface and IPv4 entries
# is because you Record after each match.
# Instead, you can Record after you have matched all entries.
# I look for what I know will be the start of the next entry in table,
# and use Continue.Record.
# Continue will continue looking for matches for the current line that is being parsed,
# but will move onto the next regex line, instead of starting back at the top of State.
# Another thing about Continue, is that you cannot do that and have a State Change,
# which is why I change to the Start state afterwards
^.+: -> Continue.Record
^${Context}: -> Start
我想解析通过 Netmiko 使用 TextFSM 执行的检查点防火墙 cphaprob -a if
。最终生成的列表格式不正确。
我已经尝试了很多 TextFSM 命令组合,但也许我只是不明白它是如何正常工作的。
原始命令输出
下面是 cphaprob -a if
原始输出。我想解析虚拟上下文(例如 'vcont 0')、接口名称(例如 'bond0')、虚拟接口(例如 'bond0.2121')及其主机名(例如“10.105.0.42”)。
vcont 0:
------
Required interfaces: 2
Required secured interfaces: 1
eth0 UP non sync(non secured), multicast
eth1 UP sync(secured), broadcast
Virtual cluster interfaces: 1
eth0 10.105.0.42
vcont 1:
------
Required interfaces: 3
Required secured interfaces: 1
eth1 UP sync(secured), broadcast
bond0 UP non sync(non secured), multicast, bond Load Sharing (bond0.2101)
bond1 UP non sync(non secured), multicast, bond Load Sharing (bond1.2126)
Virtual cluster interfaces: 3
bond0.2121 10.65.29.21
bond1.2122 10.65.29.22
bond1.2123 10.65.29.23
vcont 2:
------
Required interfaces: 3
Required secured interfaces: 1
eth1 UP sync(secured), broadcast
bond1 UP non sync(non secured), multicast, bond Load Sharing (bond1.2127)
bond0 UP non sync(non secured), multicast, bond Load Sharing (bond0.2102)
Virtual cluster interfaces: 2
bond1.4242 10.65.29.42
bond0.4243 10.65.29.43
TextFSM 模板
# template for ```cphaprob -a if``` command.
Value Context (\S+\s\d+)
Value List Interface (\S+)
Value List VirtualInterface (\S+)
Value List IPv4 (\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})
Start
^${Context}:
^${Interface}.*(UP|DOWN|Disconnected)
^Virtual cluster interfaces: \d+ -> Cluster
Cluster
^${VirtualInterface}\s+${IPv4} -> Record Start
预期结果
$ python tests/test_checkpoint_functions.py
[['vcont 0', ['eth0', 'eth1'], ['eth0'], ['10.105.0.42']],
['vcont 1', ['eth1', 'bond0', 'bond1'], ['bond0.2121', 'bond1.2122', 'bond1.2123'], ['10.65.29.21', '10.65.29.22', '10.65.29.23']],
['vcont 2', ['eth1', 'bond1', 'bond0'], ['bond1.4242', 'bond0.4243'], ['10.65.29.42', '10.65.29.43']]]
实际结果
$ python tests/test_checkpoint_functions.py
[['vcont 0', ['eth0', 'eth1'], ['eth0'], ['10.105.0.42']],
['vcont 1', ['eth1', 'bond0', 'bond1'], ['bond0.2121'], ['10.65.29.21']],
['vcont 2', ['eth1', 'bond1', 'bond0'], ['bond1.4242'], ['10.65.29.42']]]
如您所见,我只获得了第一次出现的虚拟接口及其对应的 IP 地址。原因可能是我在 Cluster 状态的模板中,我在 ^${VirtualInterface}\s+${IPv4} -> Record Start
之后记录。我只是不知道如何在相应列表中获取所有虚拟接口和 IP 地址。
Value Context (\S+\s\d+)
Value List Interface (\S+)
Value List VirtualInterface (\S+)
# Add escaping for "."
Value List IPv4 (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})
Start
^${Context}:
^${Interface}.*(UP|DOWN|Disconnected)
^Virtual cluster interfaces: \d+ -> Cluster
Cluster
^${VirtualInterface}\s+${IPv4}
# The reason for the multiple VirtualInterface and IPv4 entries
# is because you Record after each match.
# Instead, you can Record after you have matched all entries.
# I look for what I know will be the start of the next entry in table,
# and use Continue.Record.
# Continue will continue looking for matches for the current line that is being parsed,
# but will move onto the next regex line, instead of starting back at the top of State.
# Another thing about Continue, is that you cannot do that and have a State Change,
# which is why I change to the Start state afterwards
^.+: -> Continue.Record
^${Context}: -> Start