jq:使用2个独立级别键进行选择



在JSON数据上使用jq。。。

我试图在记录的同一元素中选择FromPort为80、CidrIp为0.0.0.0/0的记录。

以下是查询:

cat data.json |jq -r '.SecurityGroups | .[] | select((.IpPermissions[] | .IpRanges[] | .CidrIp == "0.0.0.0/0") and (.IpPermissions[] | .FromPort == 80))'

数据如下。

结果应仅选择Group3,而应选择Group1和Group3。我试过各种各样的谷歌搜索,但还找不到答案。

非常感谢您的帮助。

数据(Data.json(:

{
"SecurityGroups": [
{
"GroupName": "Group1",
"IpPermissions": [
{
"FromPort": 80,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
}
]
},
{
"FromPort": 6789,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
},
{
"CidrIp": "0.0.0.0/0"
}
]
}
]
},
{
"GroupName": "Group2",
"IpPermissions": [
{
"FromPort": 443,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
},
{
"CidrIp": "0.0.0.0/0"
}
]
},
{
"FromPort": 6788,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
}
]
}
]
},
{
"GroupName": "Group3",
"IpPermissions": [
{
"FromPort": 80,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
},
{
"CidrIp": "0.0.0.0/0"
}
]
},
{
"FromPort": 6789,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
}
]
}
]
}
]
}

选择.IpPermissions[] | .IpRanges[]中的迭代产生的结果与这些数组中的项一样多。对于每个true结果,您的select传递有问题的输入(可能多次(。您需要像anyall这样的聚合器来将所有结果组合为一个布尔结果,这样select就可以只传递相应输入的1或0个副本。

此外,在条件下,在and两侧迭代.IpPermissions[],这将产生结果的笛卡尔乘积。

这里有一个解决方案,如果.IpPermissions阵列中至少有一个项目与.FromPort匹配,并且.IpRanges阵列中至少一个.CidrIp匹配,则选择一个组:

jq '
.SecurityGroups[] | select(
any(.IpPermissions[]; .FromPort == 80 and
any(.IpRanges[]; .CidrIp == "0.0.0.0/0")
)
)
' data.json
{
"GroupName": "Group3",
"IpPermissions": [
{
"FromPort": 80,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
},
{
"CidrIp": "0.0.0.0/0"
}
]
},
{
"FromPort": 6789,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
}
]
}
]
}

演示

您可以适当地使用括号()and来进行如下筛选:(.FromPort==80 and (.IpRanges[] | .CidrIp=="0.0.0.0/0" ))。通过这样做,我们确保这两个条件都与IpPermissions中的一个条目匹配。

过滤器

.SecurityGroups | map(select(.IpPermissions[] 
| (.FromPort==80 and (.IpRanges[] | .CidrIp=="0.0.0.0/0" ))))

输入

{
"SecurityGroups": [
{
"GroupName": "Group1",
"IpPermissions": [
{
"FromPort": 80,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
}
]
},
{
"FromPort": 6789,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
},
{
"CidrIp": "0.0.0.0/0"
}
]
}
]
},
{
"GroupName": "Group2",
"IpPermissions": [
{
"FromPort": 443,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
},
{
"CidrIp": "0.0.0.0/0"
}
]
},
{
"FromPort": 6788,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
}
]
}
]
},
{
"GroupName": "Group3",
"IpPermissions": [
{
"FromPort": 80,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
},
{
"CidrIp": "0.0.0.0/0"
}
]
},
{
"FromPort": 6789,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
}
]
}
]
}
]
}

输出

[
{
"GroupName": "Group3",
"IpPermissions": [
{
"FromPort": 80,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
},
{
"CidrIp": "0.0.0.0/0"
}
]
},
{
"FromPort": 6789,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "1.2.3.4/24"
}
]
}
]
}
]

现在您可以看到只有Group3被输出。

演示

https://jqplay.org/s/qZvARp_5LE

或者您可以按照pmf的建议使用any/2

过滤器

.SecurityGroups[] 
| select(any(.IpPermissions[]; .FromPort==80 
and any(.IpRanges[]; .CidrIp=="0.0.0.0/0")))

演示

https://jqplay.org/s/Rw2_dtzwUA

最新更新