Tim*_*ith 9 bash select json jq
使用jq,如果父对象包含满足两个过滤器要求的子对象,如何选择它?
在这个例子中,我想选择所有子网元素,这些元素的子标记键为"Name",值为"TheName".我的例子有两个子网.第一个在错误的密钥中有"TheName".第二个子网具有我要查找的名称/值对.即"Key": "Name", "Value": "TheName"
以下选项在其中一个标签中选择具有指定值的子网,但不选择该对.它返回两个子网而不是仅返回第二个子网.
jq '.Subnets[] | select(.Tags[].Value=="TheName")' output
Run Code Online (Sandbox Code Playgroud)
如何使用jq仅选择具有我要查找的名称/值对的子网?
{
"Subnets": [
{
"VpcId": "vpc-12345678",
"SubnetId": "subnet-1234567a",
"Tags": [
{
"Key": "IgnoreThis",
"Value": "TheName"
},
{
"Key": "Name",
"Value": "NotTheName"
}
]
},
{
"VpcId": "vpc-12345678",
"SubnetId": "subnet-1234567b",
"Tags": [
{
"Key": "IgnoreThis",
"Value": "ignore"
},
{
"Key": "Name",
"Value": "TheName"
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
期望的输出是:
{
"VpcId": "vpc-12345678",
"SubnetId": "subnet-1234567b",
"Tags": [
{
"Key": "IgnoreThis",
"Value": "ignore"
},
{
"Key": "Name",
"Value": "TheName"
}
]
}
Run Code Online (Sandbox Code Playgroud)
假设你的jq有any/2一个简单而有效的解决方案:
.Subnets[]
| select( any (.Tags[]; .Key == "Name" and .Value == "TheName") )
Run Code Online (Sandbox Code Playgroud)
这会产生你想要的输出,所以我在此不再重复.
如果你的jq没有any/2,我建议升级,但如果这不方便或不是一个选项,你可以使用这个def:
def any(f;g): reduce f as $i (false; . or ($i|g));
Run Code Online (Sandbox Code Playgroud)
ps any(str; cond)可以理解为:'在流中是否有任何元素e,str,这样的元素e|cond值不是null或者false?'