关于Regex算法的问题(不一定与EXPECT相关)
Questions on Regex algorithm (not necessarily EXPECT related)
我正在尝试创建一个正则表达式来捕获我的设备的邻居详细信息(下面的示例输出)。
我可以对每一行进行硬编码,但我正在寻找更好的解决方案。也许学习一种新算法。
我对捕获设备 ID (HOST1)、接口 (GigabitEthernet0/1) 和端口 ID (GigabitEthernet2/43) 很感兴趣。对于每个邻居并将其存储在逗号分隔的列表中。
send "show cdp neighbors detail\r"
expect {
-re "-+\r\nDevice ID: (\[^\r]+)\r\n\[^\r]+\r\n\[^\r]+\r\n\[^\r]+\r\nInterface: (\[^,]+),\[^:]+: (\[^\r]+)\r\n" {
set neig $expect_out(1,string)
set localint $expect_out(2,string)
set rmint $expect_out(3,string)
lappend neighbor "$neig,$localint,$rmint"
exp_continue
}
"#" {}
}
NUMBER1#sho cdp neighbor detail
-------------------------
Device ID: HOST1
Entry address(es):
IP address: 10.10.10.1
Platform: cisco WS-C6506-E, Capabilities: Router Switch IGMP
Interface: GigabitEthernet0/1, Port ID (outgoing port): GigabitEthernet2/43
Holdtime : 126 sec
Version :
Cisco IOS Software, s72033_rp Software (s72033_rp-ADVIPSERVICESK9_WAN-M), Version 12.2(33)SXJ8, RELEASE SOFTWARE (fc5)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2014 by Cisco Systems, Inc.
Compiled Thu 21-Aug-14 09:14 by prod_rel_team
advertisement version: 2
VTP Management Domain: 'ZONE'
Native VLAN: 3
Duplex: full
Management address(es):
IP address: 10.10.10.1
-------------------------
Device ID: HOST2
Entry address(es):
IP address: 10.10.10.2
Platform: cisco WS-C6506-E, Capabilities: Router Switch IGMP
Interface: GigabitEthernet0/2, Port ID (outgoing port): GigabitEthernet2/43
Holdtime : 139 sec
Version :
Cisco IOS Software, s72033_rp Software (s72033_rp-ADVIPSERVICESK9_WAN-M), Version 12.2(33)SXJ8, RELEASE SOFTWARE (fc5)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2014 by Cisco Systems, Inc.
Compiled Thu 21-Aug-14 09:14 by prod_rel_team
advertisement version: 2
VTP Management Domain: 'ZONE'
Native VLAN: 3
Duplex: full
Management address(es):
IP address: 10.10.10.2
NUMBER1#
我上面的代码有效,只是在寻找更智能的代码?更轻松?或捕获数据的不同方式。而不是那个可怕的正则表达式。
foreach dev $neighbor {
puts "$dev"
}
Output:
HOST1,GigabitEthernet0/1,GigabitEthernet2/43
HOST2,GigabitEthernet0/2,GigabitEthernet2/43
附带说明一下,如何在 expect 中使用“{}”匹配 "occurrences"?
例如:
-re "(\r\n\[^\r]+){3}"
将匹配 3 行
我认为最好使用更简单的匹配但使用更多的匹配子句。这往往会使代码更容易理解。
send "show cdp neighbors detail\r"
expect {
-re {^Device ID: (\w+)} {
set neig $expect_out(1,string)
exp_continue
}
-re {^Interface: ([\w/]+), [^:]+: ([\w/]+)} {
set localint $expect_out(1,string)
set rmint $expect_out(2,string)
lappend neighbor "$neig,$localint,$rmint"
exp_continue
}
"#" {}
}
感兴趣的关键事物:
- 我将 RE 放在大括号中,因此在正则表达式中几乎不需要那么多反斜杠。这对可读性有很大帮助!
- 我正在使用
[\w/]
来匹配“单词字符”(基本上是字母数字)加上 /
。如果没有前面的一点,那将是丑陋的。
^
锚定到行首。 ($
到最后,但我们这里不需要它。)
- 我假设每个设备(你关心的)都有一个
Device ID
行,后面跟着一个 Interface
行,允许我独立匹配这些行并只存储值在一个简单的变量中,以便在其他子句命中时将其拾取。这是使整体 RE 更简单的关键:我们不需要匹配所有内容,只需匹配我们真正感兴趣的位即可。
{3}
(或更一般地 {3,42}
)确实匹配出现。它通常不是正确的工具,你需要非常小心你真正处理的是什么,但它确实有效。
我正在尝试创建一个正则表达式来捕获我的设备的邻居详细信息(下面的示例输出)。
我可以对每一行进行硬编码,但我正在寻找更好的解决方案。也许学习一种新算法。
我对捕获设备 ID (HOST1)、接口 (GigabitEthernet0/1) 和端口 ID (GigabitEthernet2/43) 很感兴趣。对于每个邻居并将其存储在逗号分隔的列表中。
send "show cdp neighbors detail\r"
expect {
-re "-+\r\nDevice ID: (\[^\r]+)\r\n\[^\r]+\r\n\[^\r]+\r\n\[^\r]+\r\nInterface: (\[^,]+),\[^:]+: (\[^\r]+)\r\n" {
set neig $expect_out(1,string)
set localint $expect_out(2,string)
set rmint $expect_out(3,string)
lappend neighbor "$neig,$localint,$rmint"
exp_continue
}
"#" {}
}
NUMBER1#sho cdp neighbor detail
-------------------------
Device ID: HOST1
Entry address(es):
IP address: 10.10.10.1
Platform: cisco WS-C6506-E, Capabilities: Router Switch IGMP
Interface: GigabitEthernet0/1, Port ID (outgoing port): GigabitEthernet2/43
Holdtime : 126 sec
Version :
Cisco IOS Software, s72033_rp Software (s72033_rp-ADVIPSERVICESK9_WAN-M), Version 12.2(33)SXJ8, RELEASE SOFTWARE (fc5)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2014 by Cisco Systems, Inc.
Compiled Thu 21-Aug-14 09:14 by prod_rel_team
advertisement version: 2
VTP Management Domain: 'ZONE'
Native VLAN: 3
Duplex: full
Management address(es):
IP address: 10.10.10.1
-------------------------
Device ID: HOST2
Entry address(es):
IP address: 10.10.10.2
Platform: cisco WS-C6506-E, Capabilities: Router Switch IGMP
Interface: GigabitEthernet0/2, Port ID (outgoing port): GigabitEthernet2/43
Holdtime : 139 sec
Version :
Cisco IOS Software, s72033_rp Software (s72033_rp-ADVIPSERVICESK9_WAN-M), Version 12.2(33)SXJ8, RELEASE SOFTWARE (fc5)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2014 by Cisco Systems, Inc.
Compiled Thu 21-Aug-14 09:14 by prod_rel_team
advertisement version: 2
VTP Management Domain: 'ZONE'
Native VLAN: 3
Duplex: full
Management address(es):
IP address: 10.10.10.2
NUMBER1#
我上面的代码有效,只是在寻找更智能的代码?更轻松?或捕获数据的不同方式。而不是那个可怕的正则表达式。
foreach dev $neighbor {
puts "$dev"
}
Output:
HOST1,GigabitEthernet0/1,GigabitEthernet2/43
HOST2,GigabitEthernet0/2,GigabitEthernet2/43
附带说明一下,如何在 expect 中使用“{}”匹配 "occurrences"? 例如:
-re "(\r\n\[^\r]+){3}"
将匹配 3 行
我认为最好使用更简单的匹配但使用更多的匹配子句。这往往会使代码更容易理解。
send "show cdp neighbors detail\r"
expect {
-re {^Device ID: (\w+)} {
set neig $expect_out(1,string)
exp_continue
}
-re {^Interface: ([\w/]+), [^:]+: ([\w/]+)} {
set localint $expect_out(1,string)
set rmint $expect_out(2,string)
lappend neighbor "$neig,$localint,$rmint"
exp_continue
}
"#" {}
}
感兴趣的关键事物:
- 我将 RE 放在大括号中,因此在正则表达式中几乎不需要那么多反斜杠。这对可读性有很大帮助!
- 我正在使用
[\w/]
来匹配“单词字符”(基本上是字母数字)加上/
。如果没有前面的一点,那将是丑陋的。 ^
锚定到行首。 ($
到最后,但我们这里不需要它。)- 我假设每个设备(你关心的)都有一个
Device ID
行,后面跟着一个Interface
行,允许我独立匹配这些行并只存储值在一个简单的变量中,以便在其他子句命中时将其拾取。这是使整体 RE 更简单的关键:我们不需要匹配所有内容,只需匹配我们真正感兴趣的位即可。
{3}
(或更一般地 {3,42}
)确实匹配出现。它通常不是正确的工具,你需要非常小心你真正处理的是什么,但它确实有效。