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

问题描述

我有这个数据:

{
   "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,"description" : "This is the default gateway address for X.X.X.X/27","type" : "gateway"
      },{
         "alias_domain" : "toto.com","alias_name" : "","description" : "this is a test","dns_domain" : "","environnement" : "test","fdqn" : "XXX","hostname" : "XXX","requester" : "XXX","status" : "allocated","type" : "VM"
      },{
         "ip" : "X.X.X.X","status" : "reserved"
      },"description" : "This is the broadcast address for X.X.X.X/27","type" : "broadcast"
      }
   ]
}

我想将所有状态“保留”更改为“可用”,而不更改具有网络、网关或广播状态的 ip 的状态。因此,使用 jq 我可以选择我需要的所有内容,而无需选择带有网络、网关或广播的 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"
}

但是有一种方法可以实现此输出

{
   "cidr" : "X.X.X.X/27","status" : "available"
      },"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