6

I'm trying to split a json file into various json files. The input (r1.json) looks like :

 {

    "results" : [

                {
            content 1
}
,
{
            content 2
}
,
{
            content n
}

    ]
}

I'd like the output to be n files : 1.json, 2.json, n.json. Respectively containing {content 1}, {content 2} and {content n}.

I tried :

for i in {0..24}; do cat r1.json | jq '.results[$i]' >> $i.json; done

But I have the following error: error: i is not defined

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
crocefisso
  • 793
  • 2
  • 14
  • 29
  • 2
    Give [shellcheck](http://www.shellcheck.net) a go! In this case, it says "Expressions don't expand in single quotes, use double quotes for that. – that other guy Dec 23 '15 at 00:54
  • Great link, thx a lot. It allowed me to amend my command `code`for i in {0..24}; do jq <"r1.json" ".results[$i]" > .json; done`code` – crocefisso Dec 23 '15 at 01:49

3 Answers3

8

While the above answers are correct, note that interpolating shell variables in jq scripts is a terrible idea for all but the most trivial of scripts. On any of the solutions provided, replace the following:

jq ".results[$i]"

With the following:

jq --arg i "$i" '.results[$i | tonumber]'
  • Thanks a lot for your tip @Santiago Lapresta. indeed the simple line that I mentioned above worked well without using jq --arg, but for something more elaborated, issues arise. How would you use jq --arg for nested loops. For example my script is supposed to do something like [that](https://www.dropbox.com/s/83ouwgo62eoyov1/SOF.sh?dl=0) – crocefisso Dec 27 '15 at 17:44
  • 1
    I don't really understand what that script does. Can you provide a simpler example? You shouldn't need loops outside jq most of the time; just use `range` inside the jq process instead. Regarding `--arg`, you can do more than one `--arg` invocation if you need several variables to be passed inside. Also, considering the script you link; you should probably use `-r` on jq instead of stripping quotes with `sed`. –  Dec 28 '15 at 15:36
  • finally I found the [solution](http://stackoverflow.com/questions/34509937/how-can-i-do-jq-nested-for-loops-from-bash) to the nested loop issue. Would you know some good documentation to understand how jq works ? – crocefisso Dec 30 '15 at 17:41
5

Try

for i in {0..24}; do cat r1.json | jq ".results[$i]" >> $i.json; done

Note that shell variables can't be expanded inside of single-quotes.

IHTH

shellter
  • 36,525
  • 7
  • 83
  • 90
3

The single quotes are probably what is messing you up. Bash variables are not expanded in single quotes. You are passing a literal string .results[$i] to jq. Try double quotes instead:

for i in {0..24}; do
    cat r1.json | jq ".results[$i]" >> $i.json
done
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264