Home > database >  jq - how to filter values in an inner array without knowing the key
jq - how to filter values in an inner array without knowing the key

Time:06-15

I have the following JSON:

{
  "ids": {
    "sda": [
      "scsi-0QEMU_QEMU_HARDDISK_drive-scsi2"
    ],
    "sdb": [
      "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0"
    ],
    "sdb1": [
      "lvm-pv-uuid-lvld3A-oA4k-hC19-DXzv-D0Fq-xyME-BwgJid",
      "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0-part1"
    ],
    "sdc": [
      "lvm-pv-uuid-pWes2W-dgYF-l8hG-La48-9ozH-hPdU-MOkOtf",
      "scsi-0QEMU_QEMU_HARDDISK_drive-scsi1"
    ]
  }
}

What I want to achieve is to search for .*scsi0$ in the values of the inner array and get sdb as the result.

CodePudding user response:

Using JSON jq endswith to filter results:

.ids | to_entries[] | select(.value[] | endswith("scsi0")) | .key

Results in:

"sdb"

Try it here: https://jqplay.org/s/DAhKosXXgiA


First get .ids:

{
  "sda": [
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi2"
  ],
  "sdb": [
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0"
  ],
  "sdb1": [
    "lvm-pv-uuid-lvld3A-oA4k-hC19-DXzv-D0Fq-xyME-BwgJid",
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0-part1"
  ],
  "sdc": [
    "lvm-pv-uuid-pWes2W-dgYF-l8hG-La48-9ozH-hPdU-MOkOtf",
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi1"
  ]
}

...then pipe the results to the to_entries function to convert that to an array of {key, value} objects, .ids | to_entries:

[
  {
    "key": "sda",
    "value": [
      "scsi-0QEMU_QEMU_HARDDISK_drive-scsi2"
    ]
  },
  {
    "key": "sdb",
    "value": [
      "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0"
    ]
  },
  {
    "key": "sdb1",
    "value": [
      "lvm-pv-uuid-lvld3A-oA4k-hC19-DXzv-D0Fq-xyME-BwgJid",
      "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0-part1"
    ]
  },
  {
    "key": "sdc",
    "value": [
      "lvm-pv-uuid-pWes2W-dgYF-l8hG-La48-9ozH-hPdU-MOkOtf",
      "scsi-0QEMU_QEMU_HARDDISK_drive-scsi1"
    ]
  }
]

...next stream the list of objects, .ids | to_entries[]:

{
  "key": "sda",
  "value": [
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi2"
  ]
}
{
  "key": "sdb",
  "value": [
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0"
  ]
}
{
  "key": "sdb1",
  "value": [
    "lvm-pv-uuid-lvld3A-oA4k-hC19-DXzv-D0Fq-xyME-BwgJid",
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0-part1"
  ]
}
{
  "key": "sdc",
  "value": [
    "lvm-pv-uuid-pWes2W-dgYF-l8hG-La48-9ozH-hPdU-MOkOtf",
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi1"
  ]
}

...and select from a stream of values, .ids | to_entries[] | select(.value[]) where value endswith "scsi0", select(.value[] | endswith("scsi0")) :

{
  "key": "sdb",
  "value": [
    "scsi-0QEMU_QEMU_HARDDISK_drive-scsi0"
  ]
}

...finally, get the key value, .ids | to_entries[] | select(.value[] | endswith("scsi0")) | .key:

"sdb"

Command line:

jq '.ids | to_entries[] | select(.value[] | endswith("scsi0")) | .key'

Try it here: https://jqplay.org/s/DAhKosXXgiA

CodePudding user response:

.ids | to_entries[] | select(.value[] | test(".*scsi0$")) | .key

Will print the key if any value in the array matches your regex.

If none match, there will be no output.


to_entries is uses to easy capture the key of the objects.

select to filter the values

.value[] | test(".*scsi0$") checks each value to the regex

.key and we show the key of the result


Try it online

  • Related