regexsshpython-textfsm

Regex - Match word/letters underneath a specific pattern


Very unusual one but I'm trying to match output from an SSH session that may collapse view and fall underneath the output required (like a collapsed column)...

Take a look at the example output:

      System Id     Interface          Circuit Id        State HoldTime Type     PRI
--------------------------------------------------------------------------------
rtr1.lab01.some GE0/0/1            0000000001         Up   22s      L2       -- 
thing                                                                              
rtr2.lab01.some GE0/0/2            0000000002         Up   24s      L2       -- 
thingelse                                                                              

I can match the the first line with:

^([a-zA-Z0-9][a-zA-Z0-9.-]+[a-zA-Z0-9])

which returns (rtr1.lab01.some and rtr2.lab01.some) but I'm trying to find the easiest way to match it based on the full hostname (rtr1.lab01.something and rtr2.lab01.somethingelse)

I'm also matching the rest of the output perfectly fine and able to extract the data but really can't find a way to achieve what I'm trying... Can someone point me in the right direction? To expand further (for more context... I'm using the Google TextFSM in Python to match all this data from an SSH session)


Solution

  • import re
    
    text = """System Id     Interface          Circuit Id        State HoldTime Type     PRI
    --------------------------------------------------------------------------------
    rtr1.lab01.some GE0/0/1            0000000001         Up   22s      L2       --
    thing
    rtr2.lab01.some GE0/0/2            0000000002         Up   24s      L2       --
    thingelse
    rtr2.lab01.abcd GE0/0/4            0000000003         Up   24s      L2       --
    rtr2.lab01.none GE0/0/24           0000000004         Up   24s      L2       --
    sense
    rtr2.lab01.efgh GE0/0/5            0000000003         Up   24s      L2       --
    """
    
    lines = text.rstrip().split('\n')[2:]
    n_lines = len(lines)
    current_line = -1
    
    def get_next_line():
        # Actual implementation would be reading from a file and yielding lines one line at a time
        global n_lines, current_line, lines
        current_line += 1
        # return special sentinel if "end of file"
        return  lines[current_line] if current_line < n_lines else '$'
    
    
    def get_system_id():
        line = None
        while line != '$': # loop until end of file
            if line is None: # no current line
                line = get_next_line()
                if line == '$': # end of file
                    return
            m = re.search(r'^([a-zA-Z0-9][a-zA-Z0-9.-]+[a-zA-Z0-9])', line)
            id = m[1]
            line = get_next_line() # might be sentinel
            if line != '$' and re.match(r'^[a-zA-Z0-9]+$', line): # next line just single id?
                id += line
                line = None # will need new line
            yield id
    
    for id in get_system_id():
        print(id)
    

    Prints:

    rtr1.lab01.something
    rtr2.lab01.somethingelse
    rtr2.lab01.abcd
    rtr2.lab01.nonesense
    rtr2.lab01.efgh
    

    See Python Demo