如何用jq处理lsblk递归JSON输出以生成指定CSV?
问题:从lsblk递归结构JSON生成磁盘挂载点CSV
我有一份简化后的lsblk工具输出JSON,需要生成CSV文件,展示磁盘名称及其所有挂载点(如果有的话)。目前能处理无嵌套的简单场景,但不知道如何处理包含挂载点的递归children列表。其他相关问题只针对扁平结构的旧版lsblk输出(挂载点非数组)。
期望CSV输出示例
"sda" # 无挂载点 "sdb","foo1","foo2","foo3" # 无顶层挂载点,3个(孙级)子项挂载点
注意事项
- 所有
mountpoints均为数组,可能包含多个元素或为空; mountpoints数组中可能存在null值,但数组始终存在;- 仅处理
blockdevices列表中type为disk的条目。
输入JSON示例
{ "blockdevices": [ { "type": "disk", "name": "sda", "etc" : "ignore", "mountpoints": [ null ] },{ "type": "loop", "etc" : "ignore everything" },{ "type": "disk", "name": "sdb", "etc" : "ignore", "mountpoints": [ null ], "children": [ { "name": "ignore", "etc" : "ignore", "mountpoints": [ "foo1" ] },{ "name": "ignore", "etc" : "ignore", "mountpoints": [ null ], "children": [ { "name": "ignore", "etc" : "ignore", "mountpoints": [ "foo2" ] },{ "name": "ignore", "etc" : "ignore", "mountpoints": [ "foo3" ] } ] } ] } ] }
解决方案
要处理递归的children结构,核心是深度遍历每个磁盘及其所有子节点,收集所有非null的挂载点,具体实现步骤如下:
1. 递归提取挂载点逻辑
编写递归函数遍历节点及其所有后代:
- 过滤当前节点
mountpoints数组中的null值,收集有效挂载点; - 若节点存在
children数组,递归处理每个子节点,合并子节点的有效挂载点到当前列表。
2. 示例代码(Python)
import json import csv def collect_mountpoints(node): mounts = [] # 处理当前节点挂载点,过滤null for mp in node.get('mountpoints', []): if mp is not None: mounts.append(mp) # 递归处理所有子节点 for child in node.get('children', []): mounts.extend(collect_mountpoints(child)) return mounts # 加载JSON数据 with open('lsblk_output.json', 'r') as f: data = json.load(f) # 生成CSV行 csv_rows = [] for device in data['blockdevices']: if device.get('type') == 'disk': disk_name = device['name'] all_mounts = collect_mountpoints(device) # 按示例格式构造CSV行 row = [f'"{disk_name}"'] + [f'"{mp}"' for mp in all_mounts] csv_rows.append(','.join(row)) # 打印输出或保存到文件 for line in csv_rows: print(line) # 保存到文件可替换为: # with open('disk_mounts.csv', 'w') as f: # f.write('\n'.join(csv_rows))
3. 代码说明
collect_mountpoints函数:深度遍历节点,递归收集所有有效挂载点;- 主逻辑:筛选
type为disk的设备,调用递归函数汇总挂载点,生成符合要求的CSV格式行; - 输出严格匹配示例,每个字段用双引号包裹,挂载点按遍历顺序排列。
内容的提问来源于stack exchange,提问作者QF0
相关产品推荐
相关产品推荐

