应用场景
使用netmiko等模块通过ssh从网络设备获取到的回显字符串像python字典类型的数据时, 我们可以封装一个函数, 将此类格式的字符串转换为python的字典, 方便程序处理, 如查看网络设备bfd的回显信息如下:
Total sessions: 1 Up sessions: 0 Init mode: Active
IPv4 session working in control packet mode:
Local discr: 33769 Remote discr: 0
Source IP: 100.0.0.5 Destination IP: 100.0.0.4
Destination port: 3784 Session state: Down
Interface: Ten-GigabitEthernet1/1/1
Min Tx interval: 400ms Actual Tx interval: 1000ms
Min Rx interval: 400ms Detection time: 5000ms
Rx count: 0 Tx count: 260806
Connection type: Direct Up duration: 00:00:00
Hold time: 0ms Auth mode: None
Detection mode: Async Slot: 1
Protocol: BGP
Version: 1 TTL: 255
Diag info: No Diagnostic
Hardware mode: Disable
我们想将上面的字符串分割成python的字典类型, 方便后续处理.
封装函数
def format_dict_data(dict_data_lst, replace_regex=None, line_split_str=' ', dict_split_str=':'):
"""
功能: 格式化表格格式的字符串
参数:
- dict_data: 字典格式的字符串, 格式如下:
Source IP: 1.1.1.1 Destination IP: 1.1.1.2
Interface: XGE1/1/1
- replace_regex: 替换正则表达式, 如: {r'source ip': r'source-ip'} 表示将'source ip'替换成'source-ip'
- line_split_str: 如果一行有多个键值对, 通过该分隔符将多个键值对分隔开.
- dict_split_str: 指定将字符串分隔成键值对的分隔符. 注意: 先正则替换后再进行键值对分隔
返回: [{'source-ip':'1.1.1.1', 'destination ip':'1.1.1.2', 'interface':'xge1/1/1'}]
"""
res = []
replace_regex = replace_regex or {}
for item in dict_data_lst:
item = item.lower()
for old_str_regex, new_str in replace_regex.items():
item = re.sub(old_str_regex, new_str, item, re.I)
item_tmp_lst = []
for line in item.splitlines():
tmp_lst = [_.strip() for _ in line.split(line_split_str) if dict_split_str in _]
item_tmp_lst.extend(tmp_lst)
res.append({_.split(dict_split_str)[0].strip(): _.split(dict_split_str)[1].strip() for _ in item_tmp_lst})
return res
实现代码
import netmiko
import re
from pprint import pprint
def format_dict_data(dict_data_lst, replace_regex=None, line_split_str=' ', dict_split_str=':'):
"""
功能: 格式化表格格式的字符串
参数:
- dict_data: 字典格式的字符串, 格式如下:
Source IP: 1.1.1.1 Destination IP: 1.1.1.2
Interface: XGE1/1/1
- replace_regex: 替换正则表达式, 如: {r'source ip': r'source-ip'} 表示将'source ip'替换成'source-ip'
- line_split_str: 如果一行有多个键值对, 通过该分隔符将多个键值对分隔开.
- dict_split_str: 指定将字符串分隔成键值对的分隔符. 注意: 先正则替换后再进行键值对分隔
返回: [{'source-ip':'1.1.1.1', 'destination ip':'1.1.1.2', 'interface':'xge1/1/1'}]
"""
res = []
replace_regex = replace_regex or {}
for item in dict_data_lst:
item = item.lower()
for old_str_regex, new_str in replace_regex.items():
item = re.sub(old_str_regex, new_str, item, re.I)
item_tmp_lst = []
for line in item.splitlines():
tmp_lst = [_.strip() for _ in line.split(line_split_str) if dict_split_str in _]
item_tmp_lst.extend(tmp_lst)
res.append({_.split(dict_split_str)[0].strip(): _.split(dict_split_str)[1].strip() for _ in item_tmp_lst})
return res
device = {
'device_type': 'hp_comware',
'host': '1.1.1.1',
'username': 'xxxx',
'password': 'xxxx'
}
net_connect = netmiko.ConnectHandler(**device)
output = ""
try:
output = net_connect.send_command('display bfd session verbose', cmd_verify=False)
except Exception as result:
print(f'send command failed. because \n {result}')
finally:
net_connect.disconnect()
index = output.upper().find('LOCAL DISCR')
regex_dict = {r'source ip': r'source-ip'}
res = format_dict_data(output[index:].split('\n\n'), dict_split_str=':', replace_regex=regex_dict)
pprint(res)
输出结果为字典格式
[{'actual tx interval': '1000ms',
'auth mode': 'none',
'connection type': 'direct',
'destination ip': '100.0.0.4',
'destination port': '3784',
'detection mode': 'async',
'detection time': '5000ms',
'diag info': 'no diagnostic',
'hardware mode': 'disable',
'hold time': '0ms',
'interface': 'ten-gigabitethernet1/1/1',
'local discr': '33769',
'min rx interval': '400ms',
'min tx interval': '400ms',
'protocol': 'bgp',
'remote discr': '0',
'rx count': '0',
'session state': 'down',
'slot': '1',
'source-ip': '100.0.0.5',
'ttl': '255',
'tx count': '145424',
'up duration': '00',
'version': '1'}]