pythonregexarubapython-textfsm

TEXTFSM Weird Behaviour


I have the following CLI output i need to parse:


 Status and Counters - General System Information

  System Name        : Switch-Name-2
  System Contact     :
  System Location    :

  MAC Age Time (sec) : 300

  Time Zone          : 0
  Daylight Time Rule : None

  Software revision  : WC.16.10.0009        Base MAC Addr      : ******-******

  ROM Version        : WC.16.01.0008        Serial Number      : **********

  Up Time            : 371 days             Memory   - Total   : 339,329,536
  CPU Util (%)       : 9                               Free    : 217,292,368

  IP Mgmt  - Pkts Rx : 7,218,420            Packet   - Total   : 6600
             Pkts Tx : 6,911,783            Buffers    Free    : 4281
                                                       Lowest  : 4161
                                                       Missed  : 0

And i thought i had done a good job with the following TEXTFSM template:

Value Uptime (\d+\s\S+)
Value CPU (\d+)
Value MemTotal (\S+)
Value MemFree (\S+)

Start
  ^${Uptime}
  ^\)\s+:\s${CPU}
  ^Memory\s+-\sTotal\s+:\s${MemTotal}
  ^\d+\s+Free\s+:\s+${MemFree} -> Record

However it always returns with no outputs :S

I'm pretty new to TEXTFSM but at the end of the day its just REGEXs.

I would expect the output to be the Uptime, CPU %, Memory Total and Memory Free


Solution

  • This works for me

    Value Uptime (\d+\s\S+)
    Value CPU (\d+)
    Value MemTotal (\S+)
    Value MemFree (\S+)
    
    Start
      ^Up\sTime\s+:\s${Uptime}\s+Memory\s+\-\sTotal\s+:\s+${MemTotal}
      ^CPU\sUtil\s\(\%\)\s+:\s${CPU}\s+Free\s+:\s+${MemFree} -> Record
    

    First: you forgot Up Time : for fist value.
    Second: some values are in one line so they may have to be in the same line in template.


    BTW: ^ in template means beginning of line so you can't use ^ to search element which is not at the beginning of line. You can't use ^${Uptime} to search value because there is text Up Time : before value. You can't use ^\) because ) doesn't start line. You would have to add .* to catch all other values before )

    And it seems - has special meaning in template so it needs \-


    Code which I used for tests

    import textfsm
    
    template_fh = open('template.txt')     # without `.read()` to get `file handler`
    data        = open('data.txt').read()  # with `.read()` to get `text` 
    
    template = textfsm.TextFSM(template_fh)
    data     = template.ParseText(data)
    
    print( ' | '.join(template.header) )
    # Each row of the table.
    for row in data:
      print( ' | '.join(row) )
    

    Result:

    Uptime | CPU | MemTotal | MemFree
    371 days | 9 | 339,329,536 | 217,292,368
    

    EDIT:

    The same code with data and template directly in code.
    I use io.StringIO() to create file-like object.
    This way everyone can simply copy and run code.

    import textfsm
    import io
    
    # use `io.String` to create `file-like` object
    template_fh = io.StringIO('''Value Uptime (\d+\s\S+)
    Value CPU (\d+)
    Value MemTotal (\S+)
    Value MemFree (\S+)
    
    Start
      ^Up\sTime\s+:\s${Uptime}\s+Memory\s+\-\sTotal\s+:\s+${MemTotal}
      ^CPU\sUtil\s\(\%\)\s+:\s${CPU}\s+Free\s+:\s+${MemFree} -> Record
    ''')
    
    data = '''Status and Counters - General System Information
    
    System Name        : Switch-Name-2
    System Contact     :
    System Location    :
    
    MAC Age Time (sec) : 300
    
    Time Zone          : 0
    Daylight Time Rule : None
    
    Software revision  : WC.16.10.0009        Base MAC Addr      : ******-******
    
    ROM Version        : WC.16.01.0008        Serial Number      : **********
    
    Up Time            : 371 days             Memory   - Total   : 339,329,536
    CPU Util (%)       : 9                               Free    : 217,292,368
    
    IP Mgmt  - Pkts Rx : 7,218,420            Packet   - Total   : 6600
               Pkts Tx : 6,911,783            Buffers    Free    : 4281
                                                         Lowest  : 4161
                                                         Missed  : 0
    '''
    
    template = textfsm.TextFSM(template_fh)
    data     = template.ParseText(data)
    
    print( ' | '.join(template.header) )
    # Each row of the table.
    for row in data:
      print( ' | '.join(row) )