Python 使用捕获的值作为行标识符

Python 使用捕获的值作为行标识符,python,regex,python-textfsm,Python,Regex,Python Textfsm,我需要解析此原始数据以进行处理: Port Align-Err FCS-Err Xmit-Err Rcv-Err UnderSize OutDiscards Gi0/1 1 2 3 4 5 6 Gi0/2 11 12 13 14 15

我需要解析此原始数据以进行处理:

Port        Align-Err     FCS-Err    Xmit-Err     Rcv-Err  UnderSize  OutDiscards
Gi0/1               1           2           3           4          5            6
Gi0/2               11          12          13          14         15           16


Port      Single-Col  Multi-Col   Late-Col  Excess-Col  Carri-Sen      Runts     Giants
Gi0/1              1          2          3           4          5          6          7
Gi0/2              111        122        133         144        155        166        177
为此,我使用TextFSM

我想要这个输出:

['Gi0/1', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '5', '6', '7']
['Gi0/2', '11', '12', '13', '14', '15', '16', '111', '112', '113', '114', '115', '116', '117']
我写的第一个模板是:

Value PORT (\S+(/\d+)?)
Value ALIGNERR (\d+)
Value FCSERR (\d+)
Value XMITERR (\d+)
Value RCVERR (\d+)
Value UNDERSIZE (\d+)
Value OUTDISCARDS (\d+)
Value SINGLECOL (\d+)
Value MULTICOL (\d+)
Value LATECOL (\d+)
Value EXCESSCOL (\d+)
Value CARRISEN (\d+)
Value RUNTS (\d+)
Value GIANTS (\d+)

Start
  ^Port\s+Align-Err.* -> FIRST
  ^Port\s+Single-Col.* -> SECOND

FIRST
  ^${PORT}\s+${ALIGNERR}\s+${FCSERR}\s+${XMITERR}\s+${RCVERR}\s+${UNDERSIZE}\s+${OUTDISCARDS} -> Continue.Record

SECOND
  ^${PORT}\s+${SINGLECOL}\s+${MULTICOL}\s+${LATECOL}\s+${EXCESSCOL}\s+${CARRISEN}\s+${RUNTS}\s+${GIANTS} -> Record
但是,输出不正确:

['Gi0/1', '1', '2', '3', '4', '5', '6', '', '', '', '', '', '', '']
['Gi0/2', '11', '12', '13', '14', '15', '16', '', '', '', '', '', '', '']
['Gi0/1', '1', '2', '3', '4', '5', '6', '', '', '', '', '', '', '']
['Gi0/2', '111', '122', '133', '144', '155', '166', '', '', '', '', '', '', '']
我在论坛上找到一篇文章,用纯正则表达式给出了一个解决方案:

当我调整它以适应我的需要时,我就可以满足我的需要:

但是,我无法在TextFSM模板中翻译它,它失败了。 这是我的模板:

Value PORT (\S+(/\d+)?)
Value ALIGNERR (\d+)
Value FCSERR (\d+)
Value XMITERR (\d+)
Value RCVERR (\d+)
Value UNDERSIZE (\d+)
Value OUTDISCARDS (\d+)
Value SINGLECOL (\d+)
Value MULTICOL (\d+)
Value LATECOL (\d+)
Value EXCESSCOL (\d+)
Value CARRISEN (\d+)
Value RUNTS (\d+)
Value GIANTS (\d+)

Start
  ^${PORT}\s+${ALIGNERR}\s+${FCSERR}\s+${XMITERR}\s+${RCVERR}\s+${UNDERSIZE}\s+${OUTDISCARDS}(?=.*\1\s+${SINGLECOL}\s+${MULTICOL}\s+${LATECOL}\s+${EXCESSCOL}\s+${CARRISEN}\s+${RUNTS}\s+${GIANTS}) -> Record
你知道我为什么没有火柴吗? 我是正则表达式的初学者,我似乎找不到解决方案

欢迎任何帮助:)。
提前谢谢

我终于做了我想做的事

我的团队希望使用Ansible进行格式设置,所以我不得不临时凑合一下

我用ntc来负责这个

在NTC Slack成员的帮助下,我终于让它工作了。以下是我的想法:

TextFSM repo中有一个功能记录得非常糟糕,那就是您可以在一个索引文件中组合两个共享一个公共“Key”属性的模板

因此,我创建了两个模板:

Value Key PORT (\S+(/\d+)+) 
Value ALIGNERR (\d+) 
Value FCSERR (\d+) 
Value XMITERR (\d+) 
Value RCVERR (\d+) 
Value UNDERSIZE (\d+) 
Value OUTDISCARDS (\d+) 
Start
  ^Port\s+Align-Err.* -> Begin
Begin 
 ^${PORT}\s+${ALIGNERR}\s+${FCSERR}\s+${XMITERR}\s+${RCVERR}\s+${UNDERSIZE}\s+${OUTDISCARDS} -> Record
      ^Port\s+Single-Col.* -> End
以及:

然后,我创建了一个包含以下内容的索引文件:

Template, Hostname, Vendor, Command
show_int_counter_errors1.template:show_int_counter_errors2.template, .*, cisco_ios, sh[[ow]] int[[erfaces]] cou[[nter]] er[[rors]]
您可以使用以下小脚本在Python中进行测试:

import textfsm
import sys
from textfsm import clitable
# Define Input Data
input_data = sys.stdin.read()
# Initialise CliTable with the content of the 'index' file.
cli_table = clitable.CliTable('index', '.')
# Firstly we will use attributes to match a 'show version' command on a Cisco device.
attributes = {'Command': sys.argv[1], 'Vendor': 'cisco_ios'}
# Parse Data
cli_table.ParseCmd(input_data, attributes)
print(cli_table)
要启动它,只需使用以下命令:

python3 test_table.py 'show interface counter errors' < show_int_counter_errors.txt

希望这能帮助任何人:)。

有一个更简单的方法:

from ttp import ttp
import pprint

data = """
Port        Align-Err     FCS-Err    Xmit-Err     Rcv-Err  UnderSize  OutDiscards
Gi0/1               1           2           3           4          5            6
Gi0/2               11          12          13          14         15           16

Port      Single-Col  Multi-Col   Late-Col  Excess-Col  Carri-Sen      Runts     Giants
Gi0/1              1          2          3           4          5          6          7
Gi0/2              111        122        133         144        155        166        177
"""

template = """
<group name="{{ interface }}*">
{{ interface | exclude("Port") }}   {{ counters | ROW | resub("\s+", ",", 200) | split(",") }}
</group>
"""

parser = ttp(data, template)
parser.parse()
res = parser.result()[0][0]

# res is this now:
# {'Gi0/1': [{'counters': ['1', '2', '3', '4', '5', '6']},
#            {'counters': ['1', '2', '3', '4', '5', '6', '7']}],
#  'Gi0/2': [{'counters': ['11', '12', '13', '14', '15', '16']},
#            {'counters': ['111', '122', '133', '144', '155', '166', '177']}]}

ret = []
for interface, counters in res.items():
    ret.append([interface])
    for i in counters:
        ret[-1] += list(i.values())[0]
    
pprint.pprint(ret, width=100)

# will print:
# [['Gi0/1', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '5', '6', '7'],
#  ['Gi0/2', '11', '12', '13', '14', '15', '16', '111', '122', '133', '144', '155', '166', '177']]
从ttp导入ttp
导入pprint
data=”“”
端口对齐错误FCS错误Xmit错误Rcv错误尺寸过小超出丢弃
Gi0/11143456
Gi0/2112141516
端口单列多列延迟列过量列Carri Sen Runts Giants
Gi0/11243567
Gi0/2 111 122 133 144 155 166 177
"""
模板=“”“
{接口|排除(“端口”)}{{计数器|行| resub(“\s+”,“,”,200)|拆分(“,”)}
"""
解析器=ttp(数据、模板)
parser.parse()
res=parser.result()[0][0]
#现在是这样的:
#{'Gi0/1':[{'counters':['1','2','3','4','5','6']},
#{'counters':['1','2','3','4','5','6','7']},
#'Gi0/2':[{'counters':['11','12','13','14','15','16']},
#{'counters':['111',122',133',144',155',166',177']}
ret=[]
对于接口,res.items()中的计数器:
ret.append([接口])
对于柜台中的i:
ret[-1]+=list(i.values())[0]
pprint.pprint(ret,宽度=100)
#将打印:
#[Gi0/1,1,2,3,4,5,6,1,2,3,4,5,6,7'],
#['Gi0/2','11','12','13','14','15','16','111','122','133','144','155','166','177']

-是我为使上述任务的解决方案看起来更简单而创建的库。

您必须使用
TextFSM
?或者任何其他
python
解决方案就足够了?嗨,很抱歉耽搁了!我发布了我的解决方案作为答案,太长了,无法发表评论:)。谢谢你的反馈。这看起来真的很好。谢谢,我试试看!
- hosts: all
  connection: local
  gather_facts: no

  tasks:
    - name: Formatting the errors
      ntc_show_command:
        connection: ssh
        platform: cisco_ios
        command: 'show interfaces counter errors'
        use_templates: True
        template_dir: 'PATH/TO/TEMPLATES/DIRECTORY'
        host: "{{ ansible_host }}"
        username: "{{ ansible_user }}"
        password: "{{ ansible_password }}"
 register: interface_errors

    - name: Display the registered variable
      debug:
        var: interface_errors
from ttp import ttp
import pprint

data = """
Port        Align-Err     FCS-Err    Xmit-Err     Rcv-Err  UnderSize  OutDiscards
Gi0/1               1           2           3           4          5            6
Gi0/2               11          12          13          14         15           16

Port      Single-Col  Multi-Col   Late-Col  Excess-Col  Carri-Sen      Runts     Giants
Gi0/1              1          2          3           4          5          6          7
Gi0/2              111        122        133         144        155        166        177
"""

template = """
<group name="{{ interface }}*">
{{ interface | exclude("Port") }}   {{ counters | ROW | resub("\s+", ",", 200) | split(",") }}
</group>
"""

parser = ttp(data, template)
parser.parse()
res = parser.result()[0][0]

# res is this now:
# {'Gi0/1': [{'counters': ['1', '2', '3', '4', '5', '6']},
#            {'counters': ['1', '2', '3', '4', '5', '6', '7']}],
#  'Gi0/2': [{'counters': ['11', '12', '13', '14', '15', '16']},
#            {'counters': ['111', '122', '133', '144', '155', '166', '177']}]}

ret = []
for interface, counters in res.items():
    ret.append([interface])
    for i in counters:
        ret[-1] += list(i.values())[0]
    
pprint.pprint(ret, width=100)

# will print:
# [['Gi0/1', '1', '2', '3', '4', '5', '6', '1', '2', '3', '4', '5', '6', '7'],
#  ['Gi0/2', '11', '12', '13', '14', '15', '16', '111', '122', '133', '144', '155', '166', '177']]