Json 使用jq计算多个级别

Json 使用jq计算多个级别,json,group-by,jq,aggregation,counting,Json,Group By,Jq,Aggregation,Counting,我们发现了一些与感染有关的域名。现在我们在一个.json文件中有一个DNS名称列表,我想生成一个总结输出,显示:用户列表,他们访问的唯一域,总计数。如果我还可以获得每个域名的计数,则可获得额外积分 以下是该文件的示例: {"machine": "possible_victim01", "domain": "evil.com", "timestamp":1435071870} {"machine": "possible_victim01", "domain": "evil.com", "times

我们发现了一些与感染有关的域名。现在我们在一个.json文件中有一个DNS名称列表,我想生成一个总结输出,显示:用户列表,他们访问的唯一域,总计数。如果我还可以获得每个域名的计数,则可获得额外积分

以下是该文件的示例:

{"machine": "possible_victim01", "domain": "evil.com", "timestamp":1435071870}
{"machine": "possible_victim01", "domain": "evil.com", "timestamp":1435071875}
{"machine": "possible_victim01", "domain": "soevil.com", "timestamp":1435071877}
{"machine": "possible_victim02", "domain": "bad.com", "timestamp":1435071877}
{"machine": "possible_victim03", "domain": "soevil.com", "timestamp":1435071879}
理想情况下,我希望输出类似于:

{"possible_victim01": "total": 3, {"evil.com": 2, "soevil.com": 1}}
{"possible_victim02": "total": 1, {"bad.com": 1}}
{"possible_victim03": "total": 1, {"soevil.com": 1}}
我很乐意满足于:

{"possible_victim01": "total": 3, ["evil.com", "soevil.com"]}
{"possible_victim02": "total": 1, ["bad.com"]}
{"possible_victim03": "total": 1, ["soevil.com"]}
我可以获得每个用户的记录总数,但我丢失了域列表:

cat sample.json | jq -s 'group_by(.machine) | map({machine:.[0].machine,domain:.[0].domain, count:length}) '
[{"machine": "possible_victim01", "domain": "evil.com", "count": 3},  
{"machine": "possible_victim02", "domain": "bad.com", "count": 1},
{"machine": "possible_victim03", "domain": "soevil.com", "count": 1}]
这篇文章描述了如何解决问题的后半部分。我还没有找到任何描述上半部分的内容,开始:

{"machine": "possible_victim01", "domain": "evil.com", "count":2}
{"machine": "possible_victim01", "domain": "soevil.com", "count":1}
{"machine": "possible_victim02", "domain": "bad.com", "count":1}
{"machine": "possible_victim03", "domain": "soevil.com", "count":1}

您需要执行两次
groupby
,一次按机器名分组,然后再进行子分组以获得每个域的子计数

jq查询:

group_by(.machine) | map({
    "machine": .[0].machine, 
    "total":length, 
    "domains": (group_by(.domain) | map({
        "key":.[0].domain, 
        "value":length}) | from_entries
    )
})
示例输出:

{
  "machine": "possible_victim01",
  "total": 3,
  "domains": {
    "evil.com": 2,
    "soevil.com": 1
  }
}
{
  "machine": "possible_victim02",
  "total": 1,
  "domains": {
    "bad.com": 1
  }
}
{
  "machine": "possible_victim03",
  "total": 1,
  "domains": {
    "soevil.com": 1
  }
}

按照描述的方式使用group_by是可以的,但是如果您有 按照建议读取大量行(即JSON实体) 根据提供的示例,您可能会遇到性能问题 和/或容量限制

这些问题可以通过内置的“输入”(例如JQ1.5rc1)在任何版本的jq中非常有效地解决

请注意,使用“inputs”可以使用-n选项调用jq,如下所示:

jq -n -f program.jq data.json
还请注意,这里最好是生成JSON输出,下面的内容似乎与所需内容接近:

{"possible_victim01": { "total": 3, "evildoers": {"evil.com": 2, "soevil.com": 1} },
 "possible_victim02": ...}`
下面的程序可以更简洁,但是 此处的演示旨在使流程透明, 假设对jq有基本的了解。如果这里有魔法, 也就是说,不必对“null”进行特殊处理

使用提供的示例输入,输出为:

{
  "possible_victim01": {
    "total": 3,
    "evildoers": {
      "evil.com": 2,
      "soevil.com": 1
    }
  },
  "possible_victim02": {
    "total": 1,
    "evildoers": {
      "bad.com": 1
    }
  },
  "possible_victim03": {
    "total": 1,
    "evildoers": {
      "soevil.com": 1
    }
  }
}
这是一个使用和的解决方案

如果
filter.jq
包含此筛选器,并且
data.json
包含示例数据,则命令

$ jq -M -s -f filter.jq data.json
产生

{
  "possible_victim01": {
    "total": 3,
    "domains": {
      "evil.com": 2,
      "soevil.com": 1
    }
  },
  "possible_victim02": {
    "total": 1,
    "domains": {
      "bad.com": 1
    }
  },
  "possible_victim03": {
    "total": 1,
    "domains": {
      "soevil.com": 1
    }
  }
}
$ jq -M -s -f filter.jq data.json
{
  "possible_victim01": {
    "total": 3,
    "domains": {
      "evil.com": 2,
      "soevil.com": 1
    }
  },
  "possible_victim02": {
    "total": 1,
    "domains": {
      "bad.com": 1
    }
  },
  "possible_victim03": {
    "total": 1,
    "domains": {
      "soevil.com": 1
    }
  }
}