如何使用正则表达式(TextFSM 模板)分别匹配单行 CLI 输出 (LLDP) 的三个独立部分
How to individually match three separate portions of a single line of CLI output (LLDP) with regex (TextFSM template)
我正在使用 Ansible 和 TextFSM (Python) 模板从网络设备动态提取 LLDP 信息,然后将 LLDP 输出应用于相同的设备接口描述。我目前有一个工作模型,但是我需要微调写入接口描述的内容以匹配我们的命名约定(主机名接口),其中主机名不能包含 FQDN,接口应该是接口的前三个字母案例(在本例中为 "eth"),紧接着是接口编号 (24)。最终结果看起来像 "lab-fr-sw01-eth24"
我能够使用 (\S+) 为模板中的每个变量提取适当的输出:
Value NEIGHBOR (\S+)
Value LOCAL_INTERFACE (\S+)
Value NEIGHBOR_INTERFACE (\S+)
示例 CLI 输出:
Et1 实验室-fr-sw01.test.local Ethernet24 120
唯一的问题是,有时交换机会像上面那样为 "NEIGHBOR" 变量提取 FQDN,有时则不会。现在我正在尝试为每个变量编写一个特定的正则表达式(TextFSM 模板仅使用正则表达式)语句。对于邻居变量,我试图将第二个非白色 space 字符匹配到“。”如果它存在。到目前为止,我只能使用 (^\S+) 准确地获取本地接口 (Et1) 然后当我尝试使用 ^[^.]+ 仅获取主机名时,我还包括本地接口输出 "Et1".为了匹配,我一直在使用 https://regex101.com
Et1 实验室-fr-sw01.test.local 以太网 24 120
Where LOCAL_INTERFACE = Et1, --> (^\S+)
NEIGHBOR = lab-ew-sw01.test.local and --> ^[^.]+
NEIGHBOR_INTERFACE = Ethernet24 --> ?
写入设备接口描述的预期最终结果类似于"lab-fr-sw01-eth24"。但是,因为我们有多个站点,并且每个站点名称都包含在主机名中,所以我不能依赖于逐个字母地匹配主机名。
我猜想在这里我们希望捕获字符串的三个部分,我们可以使用一个简单的表达式来实现,例如:
([a-z0-9]+)\s+([\w\-\.]+)\s([a-z0-9]+)\s([0-9]+)
Demo 1
我们想要的输出在 #1
、#2
和 #3
组中,这里我们还应用了 i
标志。
测试
# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility
import re
regex = r"([a-z0-9]+)\s+([\w\-\.]+)\s([a-z0-9]+)\s([0-9]+)"
test_str = "Et1 lab-fr-sw01.test.local Ethernet24 120"
subst = "LOCAL_INTERFACE = \1\nNEIGHBOR = \2\nNEIGHBOR_INTERFACE = \3"
# You can manually specify the number of replacements by changing the 4th argument
result = re.sub(regex, subst, test_str, 0, re.MULTILINE | re.IGNORECASE)
if result:
print (result)
# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.
Demo
正则表达式电路
jex.im 可视化正则表达式:
编辑
为了捕获 test.local
,我们只需从我们的字符列表中删除 .
:
([a-z0-9]+)\s+([\w\-]+)(.+?)\s([a-z0-9]+)\s([0-9]+)
Demo 2
我正在使用 Ansible 和 TextFSM (Python) 模板从网络设备动态提取 LLDP 信息,然后将 LLDP 输出应用于相同的设备接口描述。我目前有一个工作模型,但是我需要微调写入接口描述的内容以匹配我们的命名约定(主机名接口),其中主机名不能包含 FQDN,接口应该是接口的前三个字母案例(在本例中为 "eth"),紧接着是接口编号 (24)。最终结果看起来像 "lab-fr-sw01-eth24"
我能够使用 (\S+) 为模板中的每个变量提取适当的输出:
Value NEIGHBOR (\S+)
Value LOCAL_INTERFACE (\S+)
Value NEIGHBOR_INTERFACE (\S+)
示例 CLI 输出: Et1 实验室-fr-sw01.test.local Ethernet24 120
唯一的问题是,有时交换机会像上面那样为 "NEIGHBOR" 变量提取 FQDN,有时则不会。现在我正在尝试为每个变量编写一个特定的正则表达式(TextFSM 模板仅使用正则表达式)语句。对于邻居变量,我试图将第二个非白色 space 字符匹配到“。”如果它存在。到目前为止,我只能使用 (^\S+) 准确地获取本地接口 (Et1) 然后当我尝试使用 ^[^.]+ 仅获取主机名时,我还包括本地接口输出 "Et1".为了匹配,我一直在使用 https://regex101.com
Et1 实验室-fr-sw01.test.local 以太网 24 120
Where LOCAL_INTERFACE = Et1, --> (^\S+)
NEIGHBOR = lab-ew-sw01.test.local and --> ^[^.]+
NEIGHBOR_INTERFACE = Ethernet24 --> ?
写入设备接口描述的预期最终结果类似于"lab-fr-sw01-eth24"。但是,因为我们有多个站点,并且每个站点名称都包含在主机名中,所以我不能依赖于逐个字母地匹配主机名。
我猜想在这里我们希望捕获字符串的三个部分,我们可以使用一个简单的表达式来实现,例如:
([a-z0-9]+)\s+([\w\-\.]+)\s([a-z0-9]+)\s([0-9]+)
Demo 1
我们想要的输出在 #1
、#2
和 #3
组中,这里我们还应用了 i
标志。
测试
# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility
import re
regex = r"([a-z0-9]+)\s+([\w\-\.]+)\s([a-z0-9]+)\s([0-9]+)"
test_str = "Et1 lab-fr-sw01.test.local Ethernet24 120"
subst = "LOCAL_INTERFACE = \1\nNEIGHBOR = \2\nNEIGHBOR_INTERFACE = \3"
# You can manually specify the number of replacements by changing the 4th argument
result = re.sub(regex, subst, test_str, 0, re.MULTILINE | re.IGNORECASE)
if result:
print (result)
# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.
Demo
正则表达式电路
jex.im 可视化正则表达式:
编辑
为了捕获 test.local
,我们只需从我们的字符列表中删除 .
:
([a-z0-9]+)\s+([\w\-]+)(.+?)\s([a-z0-9]+)\s([0-9]+)