1

I'd like to iterate over a multidimensional json array in bash but haven't found a solution.

Here is what the multidimensional array would look like:

{ "FILES": [ [ "file1.yaml", "file2.yaml", "file3.yaml" ], [ "file1.json", "file2.json" ] ] } 

I'd like to convert each array into a string that will eventually be the input to a command.

So something like:

#!/bin/bash Json_Array=$(cat <<EOF { "FILES": [ [ "file1.yaml", "file2.yaml", "file3.yaml" ], [ "file1.json", "file2.json" ] ] } EOF ) function runCmd () { echo "command $1" } function runCmds () { jq -c '.FILES' <<< "$Json_Array" | while read i; do runCmd "$(echo $i | jq .)" done } runCmds 

So the output should be:

command file1.yaml file2.yaml file3.yaml command file1.json file2.json 

Thank you for any help!

1
  • What is the final objective here? Do you want something you can copy/paste to execute, or will the command actually be executed in the final script?
    – terdon
    CommentedNov 2, 2022 at 11:27

1 Answer 1

2

Insert the command with any options at the start of each array, then pass each array through @sh to create shell code. Evaluate the shell code.

Here, I'm also showing how to insert extra arguments to the command (-a and -b hello):

eval "$( jq -r '.FILES | map([ "command", "-a", "-b", "hello", .[] ])[] | @sh' file.json )" 

Given the JSON in the question, this would execute the following commands in the shell:

'command' '-a' '-b' 'hello' 'file1.yaml' 'file2.yaml' 'file3.yaml' 'command' '-a' '-b' 'hello' 'file1.json' 'file2.json' 

If you have your JSON document in some variable, $json, then use

eval "$( jq -r '.FILES | map([ "command", "-a", "-b", "hello", .[] ])[] | @sh' <<<"$json" )" 
3
  • Thank you @Kusalanada this was very helpful! It turns out I'm using the files part of the string and assigning that to a variable which I feed to a command. Interestingly the way the is formatted it keeps the "' '" and the command doesn't parse it. However I simply just trimmed off the ticks using | tr -d \' on the string and it works! Learning about the @sh was perfect thanks!CommentedNov 3, 2022 at 4:22
  • @hickersonjl The sigle quotes should make no difference. Compare running something like ls with running 'ls'. In fact, it would be crucial to keep the quotes if any of the filenames or the other arguments contain spaces or filename globbing characters.
    – Kusalananda
    CommentedNov 3, 2022 at 6:02
  • @hickersonjl If you had wanted to parse out the filenames only, then don't pass them through @sh. Instead, use @tsv or @csv and then read them as tab or comma-separated values. If you use @csv, use a CSV-aware tool to read the data as newlines, quotes and commas would be encoded as per usual in CSV files. In any case, just removing the single quotes is the wrong thing to do as it would remave single quotes from the filenames too.
    – Kusalananda
    CommentedNov 3, 2022 at 6:24

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.