用 jq 解析 lsblk

用 jq 解析 lsblk

我目前正在嘗試使用 jq 解析 lsblk 的輸出,並根據某些標準對其進行過濾。

給出以下範例輸出:

{
   "blockdevices": [
      {
         "name": "/dev/sda",
         "fstype": null,
         "size": "931.5G",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/sda1",
               "fstype": "ntfs",
               "size": "50M",
               "mountpoint": null
            },{
               "name": "/dev/sda2",
               "fstype": "ntfs",
               "size": "439.8G",
               "mountpoint": null
            },{
               "name": "/dev/sda3",
               "fstype": "vfat",
               "size": "512M",
               "mountpoint": "/boot/efi"
            },{
               "name": "/dev/sda4",
               "fstype": "ext4",
               "size": "491.2G",
               "mountpoint": "/"
            }
         ]
      },{
         "name": "/dev/sdb",
         "fstype": "crypto_LUKS",
         "size": "200GG",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/mapper/d1",
               "fstype": "btrfs",
               "size": "200G",
               "mountpoint":[
                  null
               ]
            }
         ]
      },{
         "name": "/dev/sdc",
         "fstype": "crypto_LUKS",
         "size": "100G",
         "mountpoint": null,
         "children": [
            {
               "name": "/dev/mapper/abc2",
               "fstype": "btrfs",
               "size": "100GG",
               "mountpoint": "/mnt/test"
            }
         ]
      }
   ]
}

我想檢查所有具有 fstype“crypto_LUKS”的頂級設備。然後,對於這些設備,我想檢查子設備(如果存在)是否有安裝點(不為空)。最後,我想返回符合這兩個條件的頂級設備的名稱。

因此,對於上面的範例,只會傳回 1 個符合項: /dev/sdc /dev/mapper/d1

/dev/sdc設備不會被返回,因為子設備的安裝點為空。

到目前為止我已經得到了這個:

lsblk -Jpo NAME,FSTYPE,SIZE,MOUNTPOINT | jq -r '.blockdevices[] | select(.fstype == "crypto_LUKS") '

但這只檢查 crypto_LUKS 標準,而不檢查子項的掛載點。此外,它確實會列印整個陣列條目,而不僅僅是兩個值。

我該如何解決這個問題?

答案1

若要以製表符分隔清單的形式取得區塊設備的名稱及其每個非空子掛載點:

jq -r '
    .blockdevices[]  | select(.fstype == "crypto_LUKS") as $dev |
    $dev.children[]? | select(.mountpoint | type == "string") as $mp |
    [ $dev.name, $mp.name ] | @tsv'

由於“空掛載點”實際上並不是null單一值的數組null,因此我正在測試掛載點是否為字串。

鑑於問題中的數據,這將返回

/dev/sdc        /dev/mapper/abc2

要取得滿足條件的區塊設備物件(如果這就是您所說的「整個陣列」的意思):

jq '.blockdevices[] |
    select(.fstype == "crypto_LUKS" and
           any(.children[]?; .mountpoint | type == "string"))'

這將傳回具有該fstypecrypto_LUKS並且至少有一個帶有字串的children元素的區塊設備物件。mountpoint

鑑於問題中的數據,這將返回

{
  "name": "/dev/sdc",
  "fstype": "crypto_LUKS",
  "size": "100G",
  "mountpoint": null,
  "children": [
    {
      "name": "/dev/mapper/abc2",
      "fstype": "btrfs",
      "size": "100GG",
      "mountpoint": "/mnt/test"
    }
  ]
}

相關內容