jq - jq - 从文件中合并任意数量的 json 数组时列表中的重复对象
问题描述
我正在使用 saltstack 配置 cloudwatch 代理日志(这就是为什么会有一些奇怪的语法)。我正在尝试将任意数量的包含相同架构但不同数据的文件合并到一个文件中。
文件 1
{
"logs": {
"logs_collected": {
"files":{
"collect_list": [
{
"file_name": "/var/log/suricata/eve-ips.json",
"log_group_name": "{{grains.environment_full}}SuricataIPS",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%f+0000"
}
]
}
}
}
}
文件 2
{
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_name": "/var/log/company/company-json.log",
"log_group_name": "{{grains.environment_full}}Play",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
},
{
"file_name": "/var/log/company/company-notifications.log",
"log_group_name": "{{grains.environment_full}}Notifications",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
}
]
}
}
}
}
文件 3
{
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_name": "/var/ossec/logs/alerts/alerts.json",
"log_group_name": "{{grains.environment_full}}OSSEC",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%d %H:%M:%S"
}
]
}
}
}
}
jq 查询(基于一些 SO 帮助)
jq -s '.[0].logs.logs_collected.files.collect_list += [.[].logs.logs_collected.files.collect_list | add] | unique| .[0]' web.json suricata.json wazuh-agent.json
输出
{
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_name": "/var/log/company/company-json.log",
"log_group_name": "{{grains.environment_full}}Play",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
},
{
"file_name": "/var/log/company/company-notifications.log",
"log_group_name": "{{grains.environment_full}}Notifications",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
},
{
"file_name": "/var/log/company/company-notifications.log",
"log_group_name": "{{grains.environment_full}}Notifications",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
},
{
"file_name": "/var/log/suricata/eve-ips.json",
"log_group_name": "{{grains.environment_full}}SuricataIPS",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%f+0000"
},
{
"file_name": "/var/ossec/logs/alerts/alerts.json",
"log_group_name": "{{grains['environment_full']}}OSSEC",
"log_stream_name": "{{grains.id}}",
"timezone": "UTC",
"timestamp_format": "%Y-%m-%d %H:%M:%S"
}
]
}
}
}
}
如果你已经走到这一步,谢谢你。另外需要注意的一点是,如果我更改文件的顺序,则第一个索引collect_list
总是重复的,如果web.json
是最后一个(唯一一个长度为 2),则第二个日志文件不在组中。
解决方案
作为您所做尝试的一部分,您有几个不正确的步骤。首先,转换所有“列表”数组的数组
[.[].logs.logs_collected.files.collect_list]
对于单个数组,您需要使用add
,但调用它的方式不正确。add 将输入作为对象数组,并将数组的元素加在一起作为输出。所以应该是
[.[].logs.logs_collected.files.collect_list] | add
接下来是unique
函数,它再次将一个数组作为输入,并按排序顺序生成一个相同元素的数组,并删除重复项。
[.[].logs.logs_collected.files.collect_list] | add | unique
至于第一个元素的重复,这是因为您使用的是 append 操作+=
而不是 assignment =
。因为运算符右侧的代码将来自所有对象的条目分组,所以使用追加仅将第一个对象中的值与其余对象组合在一起。
在从结果对象(..)
访问 之前,还将这些函数分组在一起。.[0]
因此,无论文件的顺序如何,将它们放在一起都会按预期工作。
jq -s '.[0].logs.logs_collected.files.collect_list = ([.[].logs.logs_collected.files.collect_list]|add|unique)|.[0]'
另一个变体使用reduce
无需使用slurp
模式-s
,而是处理inputs
标准输入上所有可用文件的 ie 内容
jq -n 'reduce inputs.logs.logs_collected.files.collect_list as $d (.; .logs.logs_collected.files.collect_list += $d)'
推荐阅读
- swift - iOS 11中文本字段的UISearchController searchBar背景颜色
- angular - Angular observable 订阅属性
- javascript - Vue组件不在HTML页面中显示数据
- node.js - 在编辑中调用编辑函数导致node.js中的无限循环
- ios - 用 zIndex 交换两个元素 onTapGesture 为动画过渡更新
- node.js - Nodejs 等到异步映射函数完成执行
- python - 在打印字典和添加用户提示以获取嵌套列表值时需要帮助 [Python]
- python - 为什么转换 Tensor 的 dtype 不能修复“RuntimeError:预期的标量类型 Double 但发现 Float”?
- c - C从数组中获取平均值的简单问题每个组件加法
- android - ViewStub 膨胀后使用 DataBinding 观察 LiveData