bash jq - 创建空数组并向其中添加对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41216894/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 15:33:21  来源:igfitidea点击:

jq - create empty array and add objects to it

bashjq

提问by Vinay

I am working on a bash script (using jq for JSON parsing)

我正在编写一个 bash 脚本(使用 jq 进行 JSON 解析)

  1. that needs to make multiple CURL calls (response has same structure but different values), apply some logic/filters and then collate all the responses in one final JSON array of objects.
  2. Loop through this final JSON array and write into a CSV in a predefined format.
  1. 这需要进行多次 CURL 调用(响应具有相同的结构但不同的值),应用一些逻辑/过滤器,然后将所有响应整理到一个最终的 JSON 对象数组中。
  2. 循环遍历这个最终的 JSON 数组并以预定义的格式写入 CSV。

Searched for a bit for both the requirements but could not find anything concrete. Please advice. The highlighted steps below (in ***) are the points where I need help.

搜索了一下这两个要求,但找不到任何具体的东西。请指教。下面突出显示的步骤(在 *** 中)是我需要帮助的地方。

Sample Flow :

样品流程:

create empty FINAL array

for(eachService is serviceList)
       a. CURL <service_response> returning JSON array of objects
       b. use jq filters to parse JSON response, apply some logic and modify elements in response as needed
       c. ***add this JSON array to FINAL array***

***LOOP through FINAL array, one object at a time a write to CSV.***

Sample Data :

样本数据 :

CURL Response 1 (ex: $curl1):
[
  {
    "id":"123",
    "startDate": "2016-12-09T00:00:00Z",
    "calls":4
  },
  {
    "id":"456",
    "startDate": "2016-12-09T00:00:00Z",
    "calls":22
  }
]

CURL Response 2 (ex : $curl2): 
[
  {
    "id":"789",
    "startDate": "2016-12-09T00:00:00Z",
    "calls":8
  },
  {
    "id":"147",
    "startDate": "2016-12-09T00:00:00Z",
    "calls":10
  }
]

NEEDED OUTPUT ($final): 
[
{
    "id":"123",
    "startDate": "2016-12-09T00:00:00Z",
    "calls":4
  },
  {
    "id":"456",
    "startDate": "2016-12-09T00:00:00Z",
    "calls":22
  },
  {
    "id":"789",
    "startDate": "2016-12-09T00:00:00Z",
    "calls":8
  },
  {
    "id":"147",
    "startDate": "2016-12-09T00:00:00Z",
    "calls":10
  }
]

回答by hek2mgl

jqcan deal with multiple input arrays. You can pipe the whole output of the loop to it:

jq可以处理多个输入数组。您可以将循环的整个输出通过管道传递给它:

for service in "$services" ; do
    curl "$service/path"
done | jq -r '.[]|[.id,.startDate,.calls]|@csv'

Note that the csv transformation can be done by @csv

请注意,csv转换可以通过 @csv

回答by peak

As @hek2mlg pointed out, it should be possible to invoke jq just once. If the input is sufficiently uniform (admittedly, maybe a big "if"), you could even avoid having to name the fields explicitly, e.g.:

正如@hek2mlg 指出的那样,应该可以只调用一次 jq。如果输入足够统一(诚然,可能是一个很大的“if”),您甚至可以避免必须明确命名字段,例如:

$ for service in "$services" ; do
    curl "$service/path"
  done | jq -sr 'add[] | [.[]] | @csv'

Output:

输出:

"123","2016-12-09T00:00:00Z",4
"456","2016-12-09T00:00:00Z",22
"789","2016-12-09T00:00:00Z",8
"147","2016-12-09T00:00:00Z",10

Note that using -s allows you to perform arbitrary computations on all the inputs, e.g. counting them.

请注意,使用 -s 允许您对所有输入执行任意计算,例如对它们进行计数。

回答by janos

You don't need a "final" array. You can process the individual JSON output of each curlcall, and parse each with the same jqscript, converting JSON input to CSV output. Something along the lines of:

您不需要“最终”数组。您可以处理每个curl调用的单独 JSON 输出,并使用相同的jq脚本解析每个输出,将 JSON 输入转换为 CSV 输出。类似的东西:

for url; do
    curl "$url" | jq 'filter-and-extract-csv-columns'
done > output.csv

Notice the redirection of the entire loop to output.csv.

注意整个循环重定向到output.csv.

This kind of streamlined processing is possible thanks to the CVS format being flat without a surrounding context as in XML or JSON. The output of multiple computations can be simply concatenated.

由于 CVS 格式是扁平的,没有像 XML 或 JSON 那样的周围上下文,因此这种简化的处理成为可能。多个计算的输出可以简单地连接起来。