24

How to extract a single value from a given json?

{
  "Vpc": {
    "InstanceTenancy": "default", 
    "State": "pending", 
    "VpcId": "vpc-123", 
    "CidrBlock": "10.0.0.0/16", 
    "DhcpOptionsId": "dopt-123"
  }
}

Tried this but with no luck:

grep -e '(?<="VpcId": ")[^"]*'

6 Answers 6

49

You probably wanted -Po, which works with your regex:

$ grep -oP '(?<="VpcId": ")[^"]*' infile
vpc-123

If GNU grep with its -P option isn't available, we can't use look-arounds and have to resort to for example using grep twice:

$ grep -o '"VpcId": "[^"]*' infile | grep -o '[^"]*$'
vpc-123

The first one extracts up to and excluding the closing quotes, the second one searches from the end of the line for non-quotes.

But, as mentioned, you'd be better off properly parsing your JSON. Apart from jq mentioned in another answer, I know of

A jq solution would be as simple as this:

$ jq '.Vpc.VpcId' infile 
"vpc-123"

Or, to get raw output instead of JSON:

$ jq -r '.Vpc.VpcId' infile 
vpc-123
4
  • Thanks, but P option is not supported out of the box on Mac OS X El Capitan. I don't want to install add-ons.
    – Centurion
    Commented Mar 18, 2016 at 6:39
  • @Centurion I think it's not possible in a single grep command then, I've added a solution that uses grep twice. Commented Mar 18, 2016 at 13:00
  • If the json is stored in a variable try this: echo $json | grep -o '"VpcId": "[^"]*' | grep -o '[^"]*$' Commented May 9, 2019 at 15:05
  • @thomasvanstone I declined that edit because it didn't seem to be correct; trying to access a non-existing field just returns null, and doesn't cause a jq error. And trying to access something that would cause an error is better done using the optional object identifier-index, ?, and still not grep. Commented Feb 9, 2022 at 18:17
6

Something like

grep '^ *"VpcId":' json.file \
  | awk '{ print $2 }' \
  | sed -e 's/,$//' -e 's/^"//' -e 's/"$//'
5

you can do:

sed -r -n -e '/^[[:space:]]*"VpcId":/s/^[^:]*: *"(.*)", *$/\1/p'

but really, using any shell tools to run regexes over JSON content is a bad idea. you should consider a much saner language like python.

python -c 'import json, sys; print(json.loads(sys.stdin.read())["Vpc"]["VpcId"]);'
0

Try this regex pattern:

\"VpcId\":\s?(\"\S+\")
1
  • Nop, doesn't return anything
    – Centurion
    Commented Mar 18, 2016 at 6:32
0

If you can install a tool I would suggest using jq jq. It allows very simple grep, with great support for piping too.

0

The OP asks for solutions using grep. In case he means using terminal, the node cli is an alternative, since support for JSON is total. One alternative could be the command node --eval "script"

echo '{"key": 42}' \
| node -e 'console.log(JSON.parse(require("fs").readFileSync(0).toString()).key)' //prints 42

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