我需要解析来自lsblk的输出。因为我是在脚本中这样做的,所以我需要一个标准化格式的输出。因此,我选择JSON格式作为输出。下面是带有一些示例输出的命令:
# lsblk -o NAME,MOUNTPOINT -J
{
"blockdevices": [
{"name": "sda", "mountpoint": null,
"children": [
{"name": "sda1", "mountpoint": "/sda1/mountpoint"},
{"name": "sda2", "mountpoint": null,
"children": [
{"name": "sda2_mapper", "mountpoint": "/sda2/mountpoint"}
]
},
{"name": "sda3", "mountpoint": null},
{"name": "sda4", "mountpoint": null}
]
},
{"name": "sdb", "mountpoint": null,
"children": [
{"name": "sdb1", "mountpoint": "/sdb1/mountpoint"},
{"name": "sdb2", "mountpoint": null}
]
},
{"name": "sdc", "mountpoint": null}
]
}我想提取所有内部节点的名称,即没有子节点的所有节点的名称。上述示例的期望输出是:
sda1
sda2_mapper
sda3
sda4
sdb1
sdb2
sdc我选择的工具是jq,这是我最近才发现的。我试过了
# jq '.blockdevices[].children[]?.name?'但这只过滤了第一级的名字。我也试过
# jq 'recurse(.name?)'但是这会返回整个文件。
是否有一种方法只返回没有子节点的节点,不管它们嵌套的深度有多深?
PS:我能够在bash或awk中实现这个需求。但是,我更喜欢使用像jq这样的工具的解决方案,该工具的具体目的是解析json文件。
发布于 2016-12-14 20:04:04
我不认为这是最简单的方法,但它似乎奏效了:
$ jq -r '.blockdevices[] | .. | objects | select(has("children")|not)| .name' tmp.json
sda1
sda2_mapper
sda3
sda4
sdb1
sdb2
sdc它递归地输出在JSON中找到的每个值,首先筛选出任何不是对象的东西,然后筛选出任何具有children键的对象。最后,您可以从其余的每个对象中选择name值。
发布于 2016-12-14 20:04:32
在输入JSON时,可以使用以下命令:
jq '.. | scalars' 发出“叶子”,开头:
"sda"
"sda1"
"/sda1/mountpoint"使用-r (原始输出)从字符串中删除引号。
https://stackoverflow.com/questions/41150539
复制相似问题