-1

I am running this simple command

category_ids=`jq '.categories | keys[]' $dictionary_location`

For some reason I have to turn it into an array to iterate properly.

while IFS=';' read -ra cat_ids; do
  for key in "${cat_ids[@]}"; do
    echo 'key:' $key;
  done
done <<< "$category_ids"

If I tried to a loop on category_ids, the word key: would print once and show all the values at once. I'm not sure if I've messed up bash or jq seeing as I have rarely had to touch bash and am brand new to jq.

Dave Stein
  • 8,653
  • 13
  • 56
  • 104
  • 4
    First, `category_ids` is *not* an array; it's a regular parameter that contains whatever string is written to standard output by `jq`. Second, `jq` can't write anything *but* a series of bytes to standard output; it certainly cannot interface directly with the shell to "inject" a non-string value into the shell's address space. (Not that a shell array is even a proper data structure; it's more like a handful of syntactic tricks to simulate an array value.) – chepner Jun 01 '21 at 20:32
  • 1
    Shell arrays are meant as another layer of quoting to allow you store arbitrary strings in a collection that doesn't rely on whitespace or any other character to separate the individual strings. It was never really meant to be used as a container data structure. – chepner Jun 01 '21 at 20:34
  • So it looks as though you have a jq program that produces a list of key names, presumably one per line, so what exactly is the problem? There is tons of information on the web and SO about creating bash arrays, so you'll need to be more specific. Btw, I can't help wondering if you wouldn't be better off doing whatever it is you are actually trying to achieve without this step (converting key names to a bash array). – peak Jun 01 '21 at 20:52
  • The documentation over at https://stedolan.github.io/jq/manual/#keys,keys_unsorted says it returns an array and this is meant to run in bash so I am not sure how to take the array straight out and use it. I could be using the wrong bash syntax here – Dave Stein Jun 01 '21 at 20:59
  • 2
    @DaveStein The shell doesn't know anything about data types, and certainly not JSON data types. `keys` produces a JSON array, but the shell has no idea that's what is it, it just sees a stream of bytes (and interprets that as a string, because that's the only data type the shell knows about). – Gordon Davisson Jun 01 '21 at 22:08

1 Answers1

0

Why is jq output a string rather than array?

jq writes it output to stdout, a file handle. File handles accept/provide sequences of bytes. This is neither a string nor an array; these concepts are not applicable here.

Backticks substitute the output of the program into the command to execute. Again, this is neither a string nor an array; these concepts are not applicable here.

As for why category_ids isn't an array, the man page for bash says the following:

An indexed array is created automatically if any variable is assigned to using the syntax name[sub‐script]=value. The subscript is treated as an arithmetic expression that must evaluate to a number. To explicitly declare an indexed array, use declare -a name (see SHELL BUILTIN COMMANDS below). declare -a name[subscript] is also accepted; the subscript is ignored.

None of these things were done, so no array was created.


I have to turn it into an array to iterate properly.

Nah, just use a while read loop that reads a line at a time.

while IFS= read -r key; do
  printf 'key: %s\n' "$key"
done <<<"$category_ids"
ikegami
  • 367,544
  • 15
  • 269
  • 518