我有一个看起来像这样的对象列表:
[
{
"ip": "1.1.1.1",
"component": "name1"
},
{
"ip": "1.1.1.2",
"component": "name1"
},
{
"ip": "1.1.1.3",
"component": "name2"
},
{
"ip": "1.1.1.4",
"component": "name2"
}
]
现在我想按组件对其进行分组和键控,并将 ip 列表分配给每个组件:
{
"name1": [
"1.1.1.1",
"1.1.1.2"
]
},{
"name2": [
"1.1.1.3",
"1.1.1.4"
]
}
我自己想出来了。我首先按
.component
进行分组,然后创建新的 ip 列表,这些列表由每个组的第一个对象的组件进行索引:
jq ' group_by(.component)[] | {(.[0].component): [.[] | .ip]}'
接受的答案不会生成有效的 json,但是:
{
"name1": [
"1.1.1.1",
"1.1.1.2"
]
}
{
"name2": [
"1.1.1.3",
"1.1.1.4"
]
}
name1
以及 name2
是有效的 json 对象,但整个输出不是。
以下
jq
语句会产生问题中指定的所需输出:
group_by(.component) | map({ key: (.[0].component), value: [.[] | .ip] }) | from_entries
输出:
{
"name1": [
"1.1.1.1",
"1.1.1.2"
],
"name2": [
"1.1.1.3",
"1.1.1.4"
]
}
欢迎提出更简单方法的建议。
如果人类可读性优于有效的 json,我建议类似......
jq -r 'group_by(.component)[] | "IPs for " + .[0].component + ": " + (map(.ip) | tostring)'
...这导致...
IPs for name1: ["1.1.1.1","1.1.1.2"]
IPs for name2: ["1.1.1.3","1.1.1.4"]
作为 @replay 技术的进一步示例,在使用其他方法多次失败后,我最终构建了一个过滤器来压缩此 Wazuh 报告(为简洁起见摘录):
{
"took" : 228,
"timed_out" : false,
"hits" : {
"total" : {
"value" : 2806,
"relation" : "eq"
},
"hits" : [
{
"_source" : {
"agent" : {
"name" : "100360xx"
},
"data" : {
"vulnerability" : {
"severity" : "High",
"package" : {
"condition" : "less than 78.0",
"name" : "Mozilla Firefox 68.11.0 ESR (x64 en-US)"
}
}
}
}
},
{
"_source" : {
"agent" : {
"name" : "100360xx"
},
"data" : {
"vulnerability" : {
"severity" : "High",
"package" : {
"condition" : "less than 78.0",
"name" : "Mozilla Firefox 68.11.0 ESR (x64 en-US)"
}
}
}
}
},
...
这是我用来提供对象数组的
jq
过滤器,每个对象都包含一个代理名称,后跟代理易受攻击的包的名称数组:
jq ' .hits.hits |= unique_by(._source.agent.name, ._source.data.vulnerability.package.name) | .hits.hits | group_by(._source.agent.name)[] | { (.[0]._source.agent.name): [.[]._source.data.vulnerability.package | .name ]}'
这里是过滤器产生的输出的摘录:
{
"100360xx": [
"Mozilla Firefox 68.11.0 ESR (x64 en-US)",
"VLC media player",
"Windows 10"
]
}
{
"WIN-KD5C4xxx": [
"Windows Server 2019"
]
}
{
"fridxxx": [
"java-1.8.0-openjdk",
"kernel",
"kernel-headers",
"kernel-tools",
"kernel-tools-libs",
"python-perf"
]
}
{
"mcd-xxx-xxx": [
"dbus",
"fribidi",
"gnupg2",
"graphite2",
...
作为 yaccob 答案的更简单替代方案,您可以使用
add
运算符将 JSON 对象列表合并为单个对象。
jq '[group_by(.component)[] | {(.[0].component): [.[] | .ip]}] | add'
输出:
{
"name1": [
"1.1.1.1",
"1.1.1.2"
],
"name2": [
"1.1.1.3",
"1.1.1.4"
]
}