Reputation: 143
I am trying to parse below big json file using bash
//part of json file
{"name": "Jenkins", "version": "Jenkins-2.22"},
{"name": "FitNesse", "version": "FitNesse-2.1"},
{"name": "Quint","version": "Quint-2.12"},
{"name": "Otto","version": "Otto-1.0"},
{"name": "Gradle","version": "Gradle-1.1"}
I am able read the line matching 'version' from json file
while read line; do
if [[ $line =~ "version" ]] ; then
echo $line; fi
done < $manifestfile
I want to store the values[Jenkins-2.22, FitNesse-2.1, Quint-2.12, Otto-1.0, Gradle-1.1] in array in my while loop
need help with tweaking my above code
Upvotes: 1
Views: 5171
Reputation: 1
Use JQ for parsing your Json easily, just install JQ, then use :
if you have a json array, and in every element you have the field version, you can use :
cat myJsonFile | jq '.[].version'
That will return a list of versions
If you want to process line by line use
while read line; do
if [[ $line =~ "version" ]] ; then
echo $line | jq .[] | jq ."version" ; fi
done < $manifestfile
Upvotes: 0
Reputation: 92854
jq is a proper tool to manipulate JSON data in Unix shell.
Let's say test.json
file contains:
[
{"name": "Jenkins", "version": "Jenkins-2.22"},
{"name": "FitNesse", "version": "FitNesse-2.1"},
{"name": "Quint","version": "Quint-2.12"},
{"name": "Otto","version": "Otto-1.0"},
{"name": "Gradle","version": "Gradle-1.1"}
]
test_json.sh script (simplified version):
#!/bin/bash
versions=$(jq '.[] | .version' test.json)
versions_arr=($versions) # contains an array of `version` key values
I must warn that the above approach ($versions)
(creating an array upon string splitting) may fail if the string $versions
has globbing characters in it.
The more "steady" approach would be using built-in read
command with -a
option to read the data wordwise into the specified array:
test_json.sh script ("steady" version):
#!/bin/bash
versions=$(jq '.[] | .version' test.json)
read -a versions_arr <<< $versions # read `version` key values into array
Now, versions_arr
is an array of version
key values.
To print for e.g. the second array value you would do:
echo ${versions_arr[1]}
The output:
"FitNesse-2.1"
Upvotes: 1
Reputation: 438283
Assuming that the sample input above is inside a JSON array in file file.json
, i.e.:
[
{"name": "Jenkins", "version": "Jenkins-2.22"},
{"name": "FitNesse", "version": "FitNesse-2.1"},
{"name": "Quint","version": "Quint-2.12"},
{"name": "Otto","version": "Otto-1.0"},
{"name": "Gradle","version": "Gradle-1.1"}
]
Note: The only change required to make the commands below work in Bash 3.x too is to replace readarray -t versions
with IFS=$'\n' read -d '' -ra versions
jq
:jq
must be installed first, but that's well worth the effort, if feasible: it enables sophisticated, robust JSON parsing.
# Extract the version numbers and read them into a Bash array.
readarray -t versions < <(jq -r '.[].version' file.json)
# Print the array.
printf '%s\n' "${versions[@]}"
The above yields:
Jenkins-2.22
FitNesse-2.1
Quint-2.12
Otto-1.0
Gradle-1.1
awk
:If you cannot install jq
, the following awk
solution is an alternative, but note that it is much less robust and relies on the JSON to be formatted exactly as above.
This warning applies to any solution using standard utilities (awk
, grep
, sed
, ...) - only a dedicated JSON parser will work robustly.
readarray -t versions < <(awk -F\" 'NF>1 { print $(NF-1) }' file.json)
# Print the array.
printf '%s\n' "${versions[@]}"
Upvotes: 3