Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning an Array Parsed With jq to Bash Script Array

Tags:

arrays

bash

jq

I parsed a json file with jq like this :

# cat test.json | jq '.logs' | jq '.[]' | jq '._id' | jq -s

It returns an array like this : [34,235,436,546,.....]

Using bash script i described an array :

# declare -a msgIds = ...

This array uses () instead of [] so when I pass the array given above to this array it won't work.

([324,32,45..]) this causes problem. If i remove the jq -s, an array forms with only 1 member in it.

Is there a way to solve this issue?

like image 244
İlker Demirci Avatar asked Jan 08 '19 08:01

İlker Demirci


3 Answers

We can solve this problem by two ways. They are:

Input string:

// test.json
{
    "keys": ["key1","key2","key3"]
}

Approach 1:

1) Use jq -r (output raw strings, not JSON texts) .

KEYS=$(jq -r '.keys' test.json)
echo $KEYS
# Output: [ "key1", "key2", "key3" ]

2) Use @sh (Converts input string to a series of space-separated strings). It removes square brackets[], comma(,) from the string.

KEYS=$(<test.json jq -r '.keys | @sh')
echo $KEYS
# Output: 'key1' 'key2' 'key3'

3) Using tr to remove single quotes from the string output. To delete specific characters use the -d option in tr.

KEYS=$((<test.json jq -r '.keys | @sh')| tr -d \') 
echo $KEYS
# Output: key1 key2 key3

4) We can convert the comma-separated string to the array by placing our string output in a round bracket(). It also called compound Assignment, where we declare the array with a bunch of values.

ARRAYNAME=(value1 value2  .... valueN)
#!/bin/bash
KEYS=($((<test.json jq -r '.keys | @sh') | tr -d \'\"))

echo "Array size: " ${#KEYS[@]}
echo "Array elements: "${KEYS[@]}

# Output: 
# Array size:  3
# Array elements: key1 key2 key3

Approach 2:

1) Use jq -r to get the string output, then use tr to delete characters like square brackets, double quotes and comma.

#!/bin/bash
KEYS=$(jq -r '.keys' test.json  | tr -d '[],"')
echo $KEYS

# Output: key1 key2 key3

2) Then we can convert the comma-separated string to the array by placing our string output in a round bracket().

#!/bin/bash
KEYS=($(jq -r '.keys' test.json  | tr -d '[]," '))

echo "Array size: " ${#KEYS[@]}
echo "Array elements: "${KEYS[@]}

# Output:
# Array size:  3
# Array elements: key1 key2 key3
like image 151
Dinesh Sonachalam Avatar answered Nov 14 '22 20:11

Dinesh Sonachalam


Use jq -r to output a string "raw", without JSON formatting, and use the @sh formatter to format your results as a string for shell consumption. Per the jq docs:

@sh:

The input is escaped suitable for use in a command-line for a POSIX shell. If the input is an array, the output will be a series of space-separated strings.

So can do e.g.

msgids=($(<test.json jq -r '.logs[]._id | @sh'))

and get the result you want.

like image 8
hobbs Avatar answered Nov 14 '22 19:11

hobbs


From the jq FAQ (https://github.com/stedolan/jq/wiki/FAQ):

𝑸: How can a stream of JSON texts produced by jq be converted into a bash array of corresponding values?

A: One option would be to use mapfile (aka readarray), for example:

mapfile -t array <<< $(jq -c '.[]' input.json)

An alternative that might be indicative of what to do in other shells is to use read -r within a while loop. The following bash script populates an array, x, with JSON texts. The key points are the use of the -c option, and the use of the bash idiom while read -r value; do ... done < <(jq .......):

#!/bin/bash
x=()
while read -r value
do
  x+=("$value")
done < <(jq -c '.[]' input.json)
like image 7
peak Avatar answered Nov 14 '22 20:11

peak