使用jq,我想获取块的“name”值,其中“Media”属性(在.session.attributeList下)包含“node7000”字符串(在示例中,json第一个数组块与其匹配 - 有两个匹配:
“值”:“节点7000”
"value": "node7000 和 node8000"
预期 jq 输出为:
“17200站”
[{
"name": "Station 17200",
"attributes": [{
"name": "EnableLog",
"value": "1"
}, {
"name": "LogFont",
"value": "0"
}, {
"name": "IdleTimer",
"value": "30"
}
],
"session": [{
"attributeList": [{
"name": "Launch",
"value": "1"
}, {
"name": "Media",
"value": "node7000"
}
]
}, {
"attributeList": [{
"name": "Group",
"value": "1"
}, {
"name": "RMedia",
"value": "1"
}
]
}, {
"attributeList": [{
"name": "Launch",
"value": ""
}, {
"name": "Media",
"value": "node7000 and node8000"
}
]
}
]
},
{
"name": "Station 17300",
"attributes": [{
"name": "EnableLog",
"value": "1"
}, {
"name": "LogFont",
"value": "0"
}, {
"name": "IdleTimer",
"value": "30"
}
],
"session": [{
"attributeList": [{
"name": "Launch",
"value": "1"
}, {
"name": "Media",
"value": "node6000"
}
]
}, {
"attributeList": [{
"name": "Group",
"value": "1"
}, {
"name": "RMedia",
"value": "1"
}
]
}, {
"attributeList": [{
"name": "Launch",
"value": ""
}, {
"name": "Media",
"value": "node6001"
}
]
}
]
}]
答案1
jq
解决方案:
jq '.[] | select([.session[].attributeList[]
| .name == "Media" and (.value | contains("node7000"))
] | any ).name' jsonfile
.[]
- 迭代输入数组的所有元素(对象)select(<condition>)
<condition>
- 如果返回该输入,则该函数将不改变其输入true
,否则不产生输出contains(element)
- 过滤器生成true
是否element
完全包含在输入中any
- 过滤器将布尔值数组作为输入,true
如果数组中的任何元素为true
输出:
"Station 17200"
答案2
这只是为了展示如何重写jq
RomanPerekhrest 提出的表达方式以便函数any(generator; condition)
的形式any
用来:
.[] |
select(
any(
.session[].attributeList[];
.name == "Media" and (.value | contains("node7000"))
)
).name
这指示函数从顶级数组的每个元素中any
提取所有值。然后,它将使用每个元素的给定条件表达式.session[].attributeList[]
从这些元素创建一个布尔数组。attributeList
如果任何布尔值是真的,然后选择顶级数组的该元素。name
然后提取并打印密钥的值。
显然,如果您想让查询字符串node7000
依赖于 shell 变量,那么您将使用--arg
将其传递到表达式中:
query_string=node7000
jq --arg media "$query_string" '.[] | select(any(.session[].attributeList[]; .name == "Media" and (.value | contains($media)))).name' file.json
如果您想传递 PCRE 正则表达式而不是字符串,请更改contains($media)
为。test($media)
这还允许我们专门寻找例如node7000
使用单词边界符号(\b
),以避免出现误报子字符串与字符串匹配的风险,例如node70001
:
jq --arg media '\bnode7000\b' '.[] | select(any(.session[].attributeList[]; .name == "Media" and (.value | test($media)))).name' file.json