将 jq 查询的结果聚合到单个数组中

Aca*_*lco 12 json jq

我有一个包含独立 JSON 对象(即不是数组)的输入文件,我想从每个对象中过滤一些字段并使用结果元素创建一个数组。它基本上是 JSON 格式的日志语句列表。

我正在使用jq这个,它工作得很好,除了我无法将所有结果对象聚合到一个数组中。

输入是这样的:

{"name":"myname", "environment":"staging", "email":"email1@example.com", "time":"2017-04-02T05:00:00.046Z"}
{"name":"myname", "environment":"staging", "email":"email2@example.com", "time":"2017-02-02T05:00:00.046Z"}
...
{"name":"myname", "environment":"staging", "email":"email3@example.com", "time":"2017-10-02T05:00:00.046Z"}
{"name":"myothername", "environment":"staging", "time":"2017-10-02T05:00:00.046Z"}
Run Code Online (Sandbox Code Playgroud)

(注意最后一个条目没有email字段,因此null如果不过滤,它将返回一个值)

从这个对象列表中,我只想获取字段emailtime,并忽略其余字段,因此我使用了以下jq查询:

jq '{email: (.email | values), time: (.time | values)}' input.json

请注意,我使用values过滤器是因为日志消息是混合的,因此并非所有 json 对象都有该email字段,因此我忽略这些字段。

我现在的问题是,即使我得到了想要的结果,我又得到了一个列表,并且我想要一个数组。

即我得到类似的东西

{"email":"email1@example.com", "time":"2017-04-02T05:00:00.046Z"}
{"email":"email2@example.com", "time":"2017-02-02T05:00:00.046Z"}
...
{"email":"email3@example.com", "time":"2017-10-02T05:00:00.046Z"}
Run Code Online (Sandbox Code Playgroud)

我想要这样:

[
    {"email":"email1@example.com", "time":"2017-04-02T05:00:00.046Z"},
    {"email":"email2@example.com", "time":"2017-02-02T05:00:00.046Z"},
    ...,
    {"email":"email3@example.com", "time":"2017-10-02T05:00:00.046Z"}
]
Run Code Online (Sandbox Code Playgroud)

我尝试了几种不同的方法,但通常都会出现错误Cannot index array with string "email",这告诉我我在数组操作上做错了。

我尝试将查询包装在map(), ie中,尝试使用和运算符map({.userEmail, .time})来获取数据。-s|+|=

我也尝试将查询包装在数组括号内,例如[{email: (.email|values), time:.time }],但我得到相同的结果对象,除了每个对象都单独包装在数组内,即

[{"email":"email1@example.com", "time":"2017-04-02T05:00:00.046Z"}]
[{"email":"email2@example.com", "time":"2017-02-02T05:00:00.046Z"}]
...
[{"email":"email3@example.com", "time":"2017-10-02T05:00:00.046Z"}]
Run Code Online (Sandbox Code Playgroud)

看起来这可能是一件容易做的事情,或者至少是一个常见的操作,但我无法找到正确的查询。

当输入不是数组时,将查询结果聚合到数组中的正确方法是什么?

pea*_*eak 12

甚至更好...

  1. 根据您的示例数据,您的基本过滤器可以简化为{email, time}

  2. 一般来说,最好避免“消耗”输入(例如,为了节省内存)。inputs根据您的情况,这可以通过使用-n 命令行选项来完成。

把它们放在一起:

jq -n '[inputs | {email, time }]' input.json
Run Code Online (Sandbox Code Playgroud)

如果您想过滤掉一些输入,您可以使用select,例如

jq -n '[inputs | select(.email) | {email, time } ]' input.json
Run Code Online (Sandbox Code Playgroud)