jq-根据其中一个值查找JSON对象,并从中获取另一个值

时间:2018-07-27 13:11:43

标签: json jq

我是最近才开始使用jq的,我想知道是否甚至可以使用这种方法。

示例:

{
  "name": "device",
  "version": "1.0.0",
  "address": [
    {
      "address": "10.1.2.3",
      "interface": "wlan1_wifi"
    },
    {
      "address": "10.1.2.5",
      "interface": "wlan2_link"
    },
    {
      "address": "10.1.2.4",
      "interface": "ether1"
    }
  ],
  "wireless": [
    {
      "name": "wlan1_wifi",
      "type": "5Ghz",
      "ssid": "wifi"
    },
    {
      "name": "wlan2_link",
      "type": "2Ghz",
      "ssid": "link"
    }
  ]
}

首先让我们将示例转换为该json对象:

cat json | jq '. | {"name": ."name", "version": ."version", "wireless": [."wireless"[] | {"name": ."name", "type": ."type", "ssid": ."ssid"}]}'
{
  "name": "device",
  "version": "1.0.0",
  "wireless": [
    {
      "name": "wlan1_wifi",
      "type": "5Ghz",
      "ssid": "wifi"
    },
    {
      "name": "wlan2_link",
      "type": "2Ghz",
      "ssid": "link"
    }
  ]
}

现在有问题。我需要为"wireless"数组分配一个地址。该地址存储在"address"数组中。

所以问题是:有一种方法可以基于"address"(在无线阵列中)和“ "name"(在地址阵列中)在interface"中找到正确的json对象为"wireless"数组中的每个json对象,然后为其分配"address"

最终结果应如下所示:

{
  "name": "device",
  "version": "1.0.0",
  "wireless": [
    {
      "name": "wlan1_wifi",
      "type": "5Ghz",
      "ssid": "wifi",
      "address": "10.1.2.3"
    },
    {
      "name": "wlan2_link",
      "type": "2Ghz",
      "ssid": "link",
      "address": "10.1.2.5"
    }
  ]
}

答案: 这是我基于@peak的answer的答案。而不是复制.wireless的内容然后再使用map,而是选择只想包含的键。这也使我可以随意定位“地址”。

(INDEX(.address[]; .interface)) as $dict 
| {name: .name, version: .version, 
wireless: [.wireless[] | {name, address: ($dict[.name]|.address), type, ssid}]}

1 个答案:

答案 0 :(得分:2)

以下内容将按照最初的请求生成输出:

(.wireless[].name) as $name
| .address[]
| select(.interface == $name)
| { wireless: {name: $name, address}}

但是,上述过滤器可能会产生多个结果,因此您可能需要相应地进行修改。

修订后的修订要求

如果您的jq具有INDEX/2(仅在jq 1.5发布后才可用),则可以简单地使用它来创建查找表:

(INDEX(.address[]; .interface)) as $dict
| {name,
   version,
   wireless: (.wireless
              | map(. + {address: ($dict[.name]|.address) }) ) }

或者(可能取决于确切的要求):

(INDEX(.address[]; .interface)) as $dict
| del(.address)
| .wireless |= map(. + {address: ($dict[.name]|.address) })

如果您的jq没有INDEX/2,那么您可以轻松地改写上面的内容(使用reduce),甚至可以更容易地从https://github.com/stedolan/jq/blob/master/src/builtin.jq中获取INDEX/2的定义。