如何用Python将Broadcom FDMI设备日志转为按Port分组的JSON?
修复FDMI日志解析代码,实现按Port分组的结构化JSON输出
问题背景
我正在处理Broadcom设备生成的FDMI日志(由fdmiShow命令导出),现有Python解析代码输出的JSON将Node Name、Port Name、Serial Number、Model等属性分散存储,无法按每个Port块进行分组。需要修改代码,将每个Port对应的所有关联属性整合到同一个对象中,生成结构清晰的JSON输出。
日志示例(fdmiShow输出片段)
FDMI Device Database: ------------------------------------------------------------------------------- Node Name: switch-01 Port Name: 0 Serial Number: ABC123 Model: BRCM-57800 ------------------------------------------------------------------------------- Node Name: switch-01 Port Name: 1 Serial Number: ABC123 Model: BRCM-57800 ------------------------------------------------------------------------------- Node Name: storage-02 Port Name: 0 Serial Number: XYZ789 Model: BRCM-9200
当前解析代码(问题版本)
import re import json def parse_fdmi_log(log_path): with open(log_path, 'r') as f: log_content = f.read() # 原代码错误地将属性拆分到不同集合中 node_names = re.findall(r'Node Name: (.*)', log_content) port_names = re.findall(r'Port Name: (.*)', log_content) serial_numbers = re.findall(r'Serial Number: (.*)', log_content) models = re.findall(r'Model: (.*)', log_content) # 分散存储属性,无法关联到单个Port result = { "node_names": [n.strip() for n in node_names], "port_names": [p.strip() for p in port_names], "serial_numbers": [s.strip() for s in serial_numbers], "models": [m.strip() for m in models] } return json.dumps(result, indent=2)
现有输出(分散结构)
{ "node_names": [ "switch-01", "switch-01", "storage-02" ], "port_names": [ "0", "1", "0" ], "serial_numbers": [ "ABC123", "ABC123", "XYZ789" ], "models": [ "BRCM-57800", "BRCM-57800", "BRCM-9200" ] }
期望输出(按Port分组)
[ { "node_name": "switch-01", "port_name": "0", "serial_number": "ABC123", "model": "BRCM-57800" }, { "node_name": "switch-01", "port_name": "1", "serial_number": "ABC123", "model": "BRCM-57800" }, { "node_name": "storage-02", "port_name": "0", "serial_number": "XYZ789", "model": "BRCM-9200" } ]
修改后的解析代码
import re import json def parse_fdmi_log(log_path): with open(log_path, 'r') as f: log_content = f.read() # 用长分隔线拆分每个独立的Port属性块 port_blocks = re.split(r'-{5,}', log_content) parsed_ports = [] for block in port_blocks: block = block.strip() # 跳过空块和日志标题块 if not block or 'FDMI Device Database:' in block: continue # 从当前块提取所有关联属性,整合到单个对象 port_data = {} if match := re.search(r'Node Name:\s*(.*)', block): port_data['node_name'] = match.group(1).strip() if match := re.search(r'Port Name:\s*(.*)', block): port_data['port_name'] = match.group(1).strip() if match := re.search(r'Serial Number:\s*(.*)', block): port_data['serial_number'] = match.group(1).strip() if match := re.search(r'Model:\s*(.*)', block): port_data['model'] = match.group(1).strip() # 只添加包含有效数据的Port对象 if port_data: parsed_ports.append(port_data) return json.dumps(parsed_ports, indent=2) # 测试调用 if __name__ == '__main__': print(parse_fdmi_log('fdmi_log.txt'))
关键修改点
- 按块拆分日志:利用日志中重复的长分隔线(
-----)将日志拆分为单个Port的属性块,确保每个块对应一个Port的完整信息 - 块内属性整合:对每个块单独提取所有关联属性,直接存入同一个字典,实现Port属性的集中存储
- 过滤无效数据:跳过空块和日志头部的标题块,避免生成无效的Port对象
- 鲁棒性处理:使用条件判断兼容日志异常情况(如某个属性缺失),不会导致解析失败
内容的提问来源于stack exchange,提问作者itsavy
相关产品推荐
相关产品推荐

