JQ:更改一些值并显示所有数据?

JQ : Change some values and display all the datas?

我有这个数据:

{
   "cidr" : "X.X.X.X/27",
   "defaultGateway" : "X.X.X.X",
   "full" : false,
   "id" : "X.X.X.X",
   "ipAddressTab" : [
      {
         "alias_domain" : null,
         "alias_name" : null,
         "description" : "This is the network address for X.X.X.X/27",
         "dnr_rr" : null,
         "dns_domain" : null,
         "environnement" : null,
         "fdqn" : null,
         "hostname" : null,
         "ip" : "X.X.X.X",
         "requester" : null,
         "status" : "reserved",
         "type" : "network"
      },
      {
         "alias_domain" : null,
         "alias_name" : null,
         "description" : "This is the default gateway address for X.X.X.X/27",
         "dnr_rr" : null,
         "dns_domain" : null,
         "environnement" : null,
         "fdqn" : null,
         "hostname" : null,
         "ip" : "X.X.X.X",
         "requester" : null,
         "status" : "reserved",
         "type" : "gateway"
      },
      {
         "alias_domain" : "toto.com",
         "alias_name" : "",
         "description" : "this is a test",
         "dns_domain" : "",
         "environnement" : "test",
         "fdqn" : "XXX",
         "hostname" : "XXX",
         "ip" : "X.X.X.X",
         "requester" : "XXX",
         "status" : "allocated",
         "type" : "VM"
      },
      {
         "alias_domain" : "toto.com",
         "alias_name" : "",
         "description" : "this is a test",
         "dns_domain" : "",
         "environnement" : "test",
         "fdqn" : "XXX",
         "hostname" : "XXX",
         "ip" : "X.X.X.X",
         "requester" : "XXX",
         "status" : "allocated",
         "type" : "VM"
      },
      {
         "ip" : "X.X.X.X",
         "status" : "reserved"
      },
      {
         "ip" : "X.X.X.X",
         "status" : "reserved"
      },
      {
         "ip" : "X.X.X.X",
         "status" : "reserved"
      },
      {
         "ip" : "X.X.X.X",
         "status" : "reserved"
      },
      {
         "alias_domain" : null,
         "alias_name" : null,
         "description" : "This is the broadcast address for X.X.X.X/27",
         "dnr_rr" : null,
         "dns_domain" : null,
         "environnement" : null,
         "fdqn" : null,
         "hostname" : null,
         "ip" : "X.X.X.X",
         "requester" : null,
         "status" : "reserved",
         "type" : "broadcast"
      }
   ]
}

我想将所有状态“保留”更改为“可用”,而不更改具有网络、网关或广播状态的 ip 的状态。因此,使用 jq 我可以 select 我需要的所有内容,而无需 select 具有网络、网关或广播的 IP 作为状态并将状态更改为可用:

cat myfile |  jq '.ipAddressTab[] | select(.status == "reserved") | select(.type != "network") | select(.type != "gateway") | select(.type != "broadcast") | .status = "available"' 

输出:

{
  "ip": "X.X.X.X",
  "status": "available"
}
{
  "ip": "X.X.X.X",
  "status": "available"
}
{
  "ip": "X.X.X.X",
  "status": "available"
}
{
  "ip": "X.X.X.X",
  "status": "available"
}

但是有一种方法可以做到这一点,以便获得此输出:

{
   "cidr" : "X.X.X.X/27",
   "defaultGateway" : "X.X.X.X",
   "full" : false,
   "id" : "X.X.X.X",
   "ipAddressTab" : [
      {
         "alias_domain" : null,
         "alias_name" : null,
         "description" : "This is the network address for X.X.X.X/27",
         "dnr_rr" : null,
         "dns_domain" : null,
         "environnement" : null,
         "fdqn" : null,
         "hostname" : null,
         "ip" : "X.X.X.X",
         "requester" : null,
         "status" : "reserved",
         "type" : "network"
      },
      {
         "alias_domain" : null,
         "alias_name" : null,
         "description" : "This is the default gateway address for X.X.X.X/27",
         "dnr_rr" : null,
         "dns_domain" : null,
         "environnement" : null,
         "fdqn" : null,
         "hostname" : null,
         "ip" : "X.X.X.X",
         "requester" : null,
         "status" : "reserved",
         "type" : "gateway"
      },
      {
         "alias_domain" : "toto.com",
         "alias_name" : "",
         "description" : "this is a test",
         "dns_domain" : "",
         "environnement" : "test",
         "fdqn" : "XXX",
         "hostname" : "XXX",
         "ip" : "X.X.X.X",
         "requester" : "XXX",
         "status" : "allocated",
         "type" : "VM"
      },
      {
         "alias_domain" : "toto.com",
         "alias_name" : "",
         "description" : "this is a test",
         "dns_domain" : "",
         "environnement" : "test",
         "fdqn" : "XXX",
         "hostname" : "XXX",
         "ip" : "X.X.X.X",
         "requester" : "XXX",
         "status" : "allocated",
         "type" : "VM"
      },
      {
         "ip" : "X.X.X.X",
         "status" : "available"
      },
      {
         "ip" : "X.X.X.X",
         "status" : "available"
      },
      {
         "ip" : "X.X.X.X",
         "status" : "available"
      },
      {
         "ip" : "X.X.X.X",
         "status" : "available"
      },
      {
         "alias_domain" : null,
         "alias_name" : null,
         "description" : "This is the broadcast address for X.X.X.X/27",
         "dnr_rr" : null,
         "dns_domain" : null,
         "environnement" : null,
         "fdqn" : null,
         "hostname" : null,
         "ip" : "X.X.X.X",
         "requester" : null,
         "status" : "reserved",
         "type" : "broadcast"
      }
   ]
}

显示所有需要更改的数据,而不仅仅是显示应该更改的行?

对于这类问题,|= 是你的朋友。

您可以选择直接的方法,例如:

.ipAddressTab
 |= map(if .status == "reserved" 
           and .type != "network"
           and .type != "gateway"
           and .type != "broadcast"
        then .status = "available" else . end)

或更微妙的:

(.ipAddressTab[]
 | select(.status == "reserved" and 
          .type != "network" and
          .type != "gateway" and
          .type != "broadcast")
).status = "available"

顺便说一句,可以通过使用 IN:

获得任一方法的 DRYer 版本
.type | IN("network", "gateway", "broadcast") | not