I'm trying to create a regex to capture the neighbor detail of my devices (example output below).
I could hard code each individual line, but I'm looking for a better solution. maybe learn a new algorithm.
I'm interested in capturing Device ID (HOST1), Interface (GigabitEthernet0/1), and Port ID (GigabitEthernet2/43). for each neighbor and store it in a list comma separated.
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#
My above code is working, just looking for a more intelligent? easier? or different way of capturing the data. Instead of that god awful regex.
foreach dev $neighbor {
puts "$dev"
}
Output:
HOST1,GigabitEthernet0/1,GigabitEthernet2/43
HOST2,GigabitEthernet0/2,GigabitEthernet2/43
on a side note, how can I match "occurrences" using "{}"within expect? for example:
-re "(\r\n\[^\r]+){3}"
would match 3 lines
I think it is going to be best to use simpler matches but more match clauses. That tends to give easier to understand code.
The key things of interest:
[\w/]
to match “word characters” (basically the alphanumerics) plus/
. That would be ugly without the preceding point though.^
anchors to the start of the line. ($
to the end, but we don't need it here.)Device ID
line followed later by anInterface
line, allowing me to match the lines independently and just store the value in a simple variable for it to be picked up when the other clause hits. This is the key to making the overall REs simpler: we don't need to match everything, just the bits that we're really interested in.{3}
(or more generally{3,42}
) does match occurrences. It's often not the right tool and you need to be very careful about what you are really dealing with, but it does work.