28

I'd like to extract the "id" key from this single line of JSON.

I believe this can be accomplished with grep, but I am not sure on the correct way.

If there is a better way that does not have dependencies, I would be interested.

Here is my example output:

{
  "data": {
    "name": "test",
    "id": "4dCYd4W9i6gHQHvd",
    "domains": ["www.test.domain.com", "test.domain.com"],
    "serverid": "bbBdbbHF8PajW221",
    "ssl": null,
    "runtime": "php5.6",
    "sysuserid": "4gm4K3lUerbSPfxz",
    "datecreated": 1474597357
  },
  "actionid": "WXVAAHQDCSILMYTV"
}

4

5 Answers 5

73

If you have a grep that can do Perl compatible regular expressions (PCRE):

$ grep -Po '"id": *\K"[^"]*"' infile.json
"4dCYd4W9i6gHQHvd"
  • -P enables PCRE
  • -o retains nothing but the match
  • "id": * matches "id" and an arbitrary amount of spaces
  • \K throws away everything to its left ("variable size positive look-behind")
  • "[^"]*" matches two quotes and all the non-quotes between them

If your grep can't do that, you an use

$ grep -o '"id": *"[^"]*"' infile.json | grep -o '"[^"]*"$'
"4dCYd4W9i6gHQHvd"

This uses grep twice. The result of the first command is "id": "4dCYd4W9i6gHQHvd"; the second command removes everything but a pair of quotes and the non-quotes between them, anchored at the end of the string ($).

But, as pointed out, you shouldn't use grep for this, but a tool that can parse JSON – for example jq:

$ jq '.data.id' infile.json
"4dCYd4W9i6gHQHvd"

This is just a simple filter for the id key in the data object. To get rid of the double quotes, you can use the -r ("raw output") option:

$ jq -r '.data.id' infile.json
4dCYd4W9i6gHQHvd

jq can also neatly pretty print your JSON:

$ jq . infile.json
{
  "data": {
    "name": "test",
    "id": "4dCYd4W9i6gHQHvd",
    "domains": [
      "www.test.domain.com",
      "test.domain.com"
    ],
    "serverid": "bbBdbbHF8PajW221",
    "ssl": null,
    "runtime": "php5.6",
    "sysuserid": "4gm4K3lUerbSPfxz",
    "datecreated": 1474597357
  },
  "actionid": "WXVAAHQDCSILMYTV"
}
9
  • 2
    @BenjaminW. Thanks! Using grep will work perfect for this situation. This works grep -o '"id": *"[^"]*"' test.txt | grep -o '"[^"]*"$' How would I remove the quotes as well, leaving only the ID?
    – petebocken
    Commented Sep 23, 2016 at 13:11
  • 3
    @petebocken You'd have to remove the last quote from the first command and the first and last quote from the second one: grep -o '"id": *"[^"]*' test.txt | grep -o '[^"]*$' Commented Sep 23, 2016 at 13:28
  • 1
    @BenjaminW. I tried several edits and for some reason couldn't find the right one to remove. This works perfect, thanks!
    – petebocken
    Commented Sep 23, 2016 at 13:30
  • @BenjaminW. '"id": *\K"[^"]*"' this works for me, but how can i make sure i remove the double quotes from the result. Commented Jul 22, 2020 at 17:30
  • 1
    @BenjaminW. I tried the 2 grep solution and it worked :) cheers Commented Jul 22, 2020 at 19:03
10

Just pipe your data to jq and select by keys

"data": {
    "name": "test",
    "id": "4dCYd4W9i6gHQHvd",
    "domains": [
      "www.test.domain.com",
      "test.domain.com"
    ],
    "serverid": "bbBdbbHF8PajW221",
    "ssl": null,
    "runtime": "php5.6",
    "sysuserid": "4gm4K3lUerbSPfxz",
    "datecreated": 1474597357
  },
  "actionid": "WXVAAHQDCSILMYTV"
} | jq '.data.id'     

# 4dCYd4W9i6gHQHvd

Tutorial Here

8

I found myself that the best way is to use python, as it handles JSON natively and is preinstalled on most systems these days, unlike jq:

$ python -c 'import sys, json; print(json.load(sys.stdin)["data"]["id"])' < infile.json
4dCYd4W9i6gHQHvd
3
  • 2
    Liking this answer because it uses what is there. It's all too easy to just go installing more and more to solve things like this. Very simple, but overlooked approach!
    – kmjb
    Commented May 22, 2020 at 16:56
  • best and easy solution
    – Vovan
    Commented Mar 17, 2022 at 13:12
  • This can also be piped from curl request like so: curl https://jsonplaceholder.typicode.com/todos/1 | python -c 'import sys, json; print(json.load(sys.stdin)["title"])' and it works for both python v2 & v3.
    – Ibrahim.H
    Commented Mar 13, 2023 at 7:25
6

No python ,jq, awk, sed just GNU grep:

#!/bin/bash
json='{"data": {"name": "test", "id": "4dCYd4W9i6gHQHvd", "domains": ["www.test.domain.com", "test.domain.com"], "serverid": "bbBdbbHF8PajW221", "ssl": null, "runtime": "php5.6", "sysuserid": "4gm4K3lUerbSPfxz", "datecreated": 1474597357}, "actionid": "WXVAAHQDCSILMYTV"}' 
        
echo $json | grep -o '"id": "[^"]*' | grep -o '[^"]*$'

Tested & working here: https://ideone.com/EG7fv7

source: https://brianchildress.co/parse-json-using-grep

1
  • It works, however the only issue comes when piping the output of curl to grep, since curl uses the stderr instead of stdout to output the results, we must pipe from the stderr (using 2>&1) like so:curl https://jsonplaceholder.typicode.com/todos/1 2>&1 | grep -o '"title": "[^"]*' | grep -o '[^"]*$'.
    – Ibrahim.H
    Commented Mar 13, 2023 at 7:43
0

$ grep -oP '"id": *"\K[^"]*' infile.json

4dCYd4W9i6gHQHvd

Hopefully it will work for all. As this will work for me to print without quotes.

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