最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

json - jq: how do I handle recursion in this case? - Stack Overflow

programmeradmin1浏览0评论

I have JSON output as shown below (the output of lsblk, greatly simplified). I need to generate CSV output which shows the name of a disk, together with a list of mount points, if any. I can generate this for simple cases, but the problem is that there's a recursive children list, containing additional mountpoints, which I don't know how to handle.

There are a couple of other SO questions which ask specifically about parsing lsblk output, but they show a simpler (old?) lsblk output, which is flat (and with mountpoints which aren't arrays).

For the example below, I'd like to get CSV output that looks like (without the comments, obviously):

"sda"                       # no mountpoints
"sdb","foo1","foo2","foo3"  # no top-level mountpoint, 3 [grand]children

Note:

  1. All mountpoints are arrays. Presumably they can contain more than one element (or no elements), but I've never seen this
  2. Any mountpoints can contain null entries, but it seems like the array is always present
  3. The blockdevices object contains a list, but only entries of type disk are relevant

Any help much appreciated - I've spent several hours trying to find a walk/recurse solution which handles the children.

{
   "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" ]
                  }
               ]
            }
         ]
      }
   ]
}

I have JSON output as shown below (the output of lsblk, greatly simplified). I need to generate CSV output which shows the name of a disk, together with a list of mount points, if any. I can generate this for simple cases, but the problem is that there's a recursive children list, containing additional mountpoints, which I don't know how to handle.

There are a couple of other SO questions which ask specifically about parsing lsblk output, but they show a simpler (old?) lsblk output, which is flat (and with mountpoints which aren't arrays).

For the example below, I'd like to get CSV output that looks like (without the comments, obviously):

"sda"                       # no mountpoints
"sdb","foo1","foo2","foo3"  # no top-level mountpoint, 3 [grand]children

Note:

  1. All mountpoints are arrays. Presumably they can contain more than one element (or no elements), but I've never seen this
  2. Any mountpoints can contain null entries, but it seems like the array is always present
  3. The blockdevices object contains a list, but only entries of type disk are relevant

Any help much appreciated - I've spent several hours trying to find a walk/recurse solution which handles the children.

{
   "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" ]
                  }
               ]
            }
         ]
      }
   ]
}
Share Improve this question asked Nov 20, 2024 at 11:09 QF0QF0 5291 gold badge4 silver badges18 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

Probably not the cleanest way, but we could:

  1. Filter on select(.type == "disk") to prevent empty starting arrays.
  2. Recursive (..) get all .mountpoints
    (or empty array as fallback (// []))
  3. flatten the arrays to get a single output.
  4. Then remove all null from the arrays (values).

.blockdevices[] | select(.type == "disk") | [ 
    .name, 
    (.. | (.mountpoints? // []) | flatten[] | values) 
]

output:

[
  "sda"
]
[
  "sdb",
  "foo1",
  "foo2",
  "foo3"
]

JqPlay Demo

发布评论

评论列表(0)

  1. 暂无评论