使用jq解析JSON格式

5 bash json jq

我需要解析输出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}
   ]
}
Run Code Online (Sandbox Code Playgroud)

我想提取所有最内层节点的名称,即所有没有子节点的节点的名称.上述样本的所需输出为:

sda1
sda2_mapper
sda3
sda4
sdb1
sdb2
sdc
Run Code Online (Sandbox Code Playgroud)

我选择的工具是jq我最近才发现的.我试过了

# jq '.blockdevices[].children[]?.name?'
Run Code Online (Sandbox Code Playgroud)

但这只会过滤第一级别的名称.我也尝试过

# jq 'recurse(.name?)'
Run Code Online (Sandbox Code Playgroud)

但这会返回整个文件.

有没有办法只返回没有子节点的节点,无论它们嵌套多深?

PS:我有能力在bash或中实施要求awk.但是,我更喜欢使用类似工具的解决方案jq,其具体目的是解析json文件.

che*_*ner 0

我认为这不是最简单的方法,但它似乎有效:

$ jq -r '.blockdevices[] | .. | objects | select(has("children")|not)| .name' tmp.json
sda1
sda2_mapper
sda3
sda4
sdb1
sdb2
sdc
Run Code Online (Sandbox Code Playgroud)

它递归地输出在 JSON 中找到的每个值,首先过滤掉任何非对象的内容,然后过滤掉任何具有键的对象children。最后,您可以name从每个剩余对象中选择值。