Questions on Regex algorithm (not necessarily EXPECT related)

169 views Asked by At

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

1

There are 1 answers

0
Donal Fellows On BEST ANSWER

I think it is going to be best to use simpler matches but more match clauses. That tends to give easier to understand code.

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
    }
    "#" {}
}

The key things of interest:

  • I'm putting the REs in braces so I don't need nearly so many backslashes in the regular expressions. This helps readability a lot!
  • I'm using [\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.)
  • I'm assuming that every device (that you care about) will have a Device ID line followed later by an Interface 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.