4

I have a variable with nested json,

a={"version":"3.0","user":"unknown_unknown","dateGenerated":"2020-07-08T11:53:23Z","status":"OK","data":[{"parameter":"t_2m:C","coordinates":[{"lat":39.23054,"lon":9.11917,"dates":[{"date":"2020-07-08T15:53:23Z","value":25.1}]}]}]}

Looking for a way to grep the "value" in the nested json (like the one highlighted) in variable a.

I'am using grep and jq but I can't show value, I show "dates" (echo $result | grep -Po '"dates":.*?[^\\],.*?[^\\]"') but not just the value.

Any help?

  • Will there always be just one value? What operating system are you using? Do you have the GNU tools? Does your grep support -o? And, of so, would something as simple as grep -oP '(?<=value":)[0-9.]+' <<<"$a" do? – terdon Jul 8 at 12:31
10

You want the "value" from (the first object in the "dates" array) from (the first object in the "coordinates" array) from (the first object in the "data" array)

$ a='{"version":"3.0","user":"unknown_unknown","dateGenerated":"2020-07-08T11:53:23Z","status":"OK","data":[{"parameter":"t_2m:C","coordinates":[{"lat":39.23054,"lon":9.11917,"dates":[{"date":"2020-07-08T15:53:23Z","value":25.1}]}]}]}'
$ echo "$a" | jq -r '.data[0].coordinates[0].dates[0].value'
25.1
| improve this answer | |
7

You may also want to consider installing gron, which is a utility to "Make JSON greppable!".

With a defined as in your question,

echo $a | gron

returns

json.data = [];
json.data[0] = {};
json.data[0].coordinates = [];
json.data[0].coordinates[0] = {};
json.data[0].coordinates[0].dates = [];
json.data[0].coordinates[0].dates[0] = {};
json.data[0].coordinates[0].dates[0].date = "2020-07-08T15:53:23Z";
json.data[0].coordinates[0].dates[0].value = 25.1;
json.data[0].coordinates[0].lat = 39.23054;
json.data[0].coordinates[0].lon = 9.11917;
json.data[0].parameter = "t_2m:C";
json.dateGenerated = "2020-07-08T11:53:23Z";
json.status = "OK";
json.user = "unknown_unknown";
json.version = "3.0";

which does indeed make it easy to process:

$ echo $a | gron | sed -n '/value/{s/.* //; s/;//; p;}'
25.1

$ echo $a | gron | awk '/value/ {sub(/;/,""); print $NF;}'
25.1
| improve this answer | |
  • thanks for the pointer to gron .. been lookin for something like that – rr0ss0rr Jul 8 at 18:13
4

Using Miller, with its default JSON array flattening:

$ mlr --ijson --onidx cut -f 'data:0:coordinates:0:dates:0:value' <<<"$a"
25.1

or regex-matching the flattened element name

$ mlr --ijson --onidx cut -r -f 'value$' <<<"$a"
25.1
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.