Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run a command for each item in jq array

Tags:

bash

jq

This is how my input file looks like:

[
  {
    "ConfigType": "ABC",
    "Prop1": 3,
    "Prop2": 30
  },
  {
    "ConfigType": "XYZ",
    "Prop3": "Hello",
    "Prop4": "World",
    "Prop5": "Application"
  }
]

I need to prepare insert statement for each item.

This is how my jq command looks like which gives me each item.

cat app-cnfg.json |  jq -r ".[]"

How do I execute aws dynamodb put-item --table-name "xxx" --item <<array's element>>?

like image 558
Asdfg Avatar asked Dec 05 '17 18:12

Asdfg


People also ask

Is jq fast?

jq's "streaming parser" is known to be slow (and maybe slower than need be), but there may be differences between versions of jq.

Does jq use JSONPath?

JSONPath distinguishes between the "root object or element" ($) and "the current object or element" (.). jq simply uses . to refer to the current JSON entity and so it is context-dependent: it can refer to items in the input stream of the jq process as a whole, or to the output of a filter.

What is shell command jq?

The JQ command is used to transform JSON data into a more readable format and print it to the standard output on Linux. The JQ command is built around filters which are used to find and print only the required data from a JSON file.

Can jq write JSON?

jq is an amazing little command line utility for working with JSON data.


2 Answers

You can pipe to xargs:

jq -c '.[]' app-cnfg.json \
    | xargs -L 1 aws dynamodb put-item --table-name "xxx" --item

The -c option to jq makes sure each element is on a single line, and the -L 1 option to xargs makes sure that the command is called once per item.

If you wanted to avoid potential problems with trailing whitespace (which would make args treat the following line as continuation of the current one), you can get your objects zero byte separated:

jq -j '.[] | tostring + "\u0000"' app-cnfg.json \
    | xargs -0 -n1 aws dynamodb put-item --table-name "xxx" --item

The -j option suppresses newlines from jq, tostring stringifies the objects and + "\u0000" appends a zero byte.

xargs -0 -n1 expects zero byte delimited input and runs the command for each argument once.

like image 163
Benjamin W. Avatar answered Oct 19 '22 22:10

Benjamin W.


You can apply the filter to extract each element of the JSON array and feed it to an array in bash and iterate over its content later. Assuming you have bash 4.0 or greater, you can use mapfile command as

mapfile -t configArr < <(jq -c '.[]'  < app-cnfg.json)

and now we loop over the array, to run the command for each config item,

for config in "${configArr[@]}"; do
    aws dynamodb put-item --table-name "xxx" --item "$config"
done

(or) use a more efficient way to read from an input data stream using a while loop and the read command (works on bash versions that don't support mapfile or readarray)

while IFS= read -r config; do
    aws dynamodb put-item --table-name "xxx" --item "$config"
done< <(jq -c '.[]' < app-cnfg.json)
like image 36
Inian Avatar answered Oct 19 '22 21:10

Inian