简体   繁体   中英

extract specific key value from json in bash if key matches

I have a json content (output.json)

{"project": {"id": "A", "content": [{"name": "XYZ", "location": "Berlin", "comments":""}, {"name": "ABC", "location": "NewYork", "comments": "Hwllo"}, {"name": "DEF", "location": "Paris", "comments": "Success"}]}}

I would like to extract location key with value when name matches say ABC from the above json using bash or shell commands

I tried something like below which gives be content within curly braces. but not sure on searching specific key.

cat output.json | grep -o -e "{.*}"

Output expectations: if name matches ABC , get output as "location":"NewYork"

Any suggestions on processing further?

There may be better ways to do it, in a quick twisted way is here.

cat output.json | sed 's/"name"/\n"name"/g' | grep '"name"' | awk -F',' '{print $2}'

Add | grep <preferred name> | grep <preferred name> also if need to filter based on name.

For extracting from json you should use jq if you can. According to authors "jq is like sed for JSON data" (source) .

In your case it should be:

$ jq -r '.project' output.json | jq -r '.content' | jq '.[] | select(.name=="ABC")' | jq -r '.location'

Output will be:

NewYork

To get output which you required so:

"location":"NewYork"

You can use:

echo "\"location\":$(jq -r '.project' output.json | jq -r '.content' | jq '.[] | select(.name=="ABC")' | jq '.location')"

Before you use jq you should install it on Debian and Ubuntu it will be:

$ sudo apt install jq

for other OS you should check this site .

Use Perl

$ perl -0777 -lne ' while(/"name":\s+"ABC",\s+"location":\s+(\S+)/msg) { print "$1\n" } ' output.json
"NewYork",
$ cat output.json
{"project": {"id": "A", "content": [{"name": "XYZ", "location": "Berlin", "comments":""}, {"name": "ABC", "location": "NewYork", "comments": "Hwllo"}, {"name": "DEF", "location": "Paris", "comments": "Success"}]}}
$

Please use a JSON parser for processing JSON.
With Xidel it's as simple as:

xidel -s output.json -e '($json//content)()[name="ABC"]/location'

Alternatively:

xidel -s output.json -e '$json/(.//content)()[name="ABC"]/location'

or in full:

xidel -s output.json -e '$json/project/(content)()[name="ABC"]/location'

The above is XPath notation ( example #11, Reading JSON ). Dot notation (like jq ) is also possible:

xidel -s output.json -e '($json).project.content()[name="ABC"].location'

[edit]
Commands above put out NewYork and I just realized you require the output to be "location":"NewYork" . Xidel can do that too:

xidel -s output.json -e '($json//content)()[name="ABC"]/concat("""location"":""",location,"""")'

[/edit]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM