1

I am working on an assignment about parsing JSON by shell script. Is there any way that I can get the values from the JSON when executing it? For example, I'like to output id, body, and age's value. I am trying to use cut, sed, grep, but not jq. Should I use for-loop? Currently, I only can redirect the json to a txt file.

{
"postId": 1,
"id": 1,
"name": "id labore ex et quam laborum",
"email": "Eliseo@gardner.biz",
"body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora",
"age": 28
}
Amy
  • 49
  • 7
  • 3
    `jq` is the right tool for the job. Why aren't you using it? – that other guy Jun 16 '20 at 03:08
  • The assignment requires not using jq, only sed, grep, etc. – Amy Jun 16 '20 at 03:27
  • You should show your best effort so far. That will guide those who might help. Does the JSON input consist of a single object as shown in the question, or could there be multiple objects? When you say "output ID, body and age", what form should that output take? – Jonathan Leffler Jun 16 '20 at 03:58
  • 1
    `sed` and `grep` are both regular-expression-based, and therefore not capable of parsing things like JSON that can contain nested syntax (e.g. JSON allows arrays within arrays within arrays within....). It's in the same category as [HTML](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454). You can fake it if the JSON is simple enough, but parsing JSON with regex will fail if the JSON isn't in the exact format you expect. – Gordon Davisson Jun 16 '20 at 04:34
  • @ Gordon, If I understand you correctly, `sed` and `grep` can not doing like remove the bracket, comma, and the keys. Then only leaves those values? – Amy Jun 16 '20 at 07:15
  • @Amy regex tools can do things like removing brackets, commas, and keys, but suppose there were key with nested content, like `"previous_data": { "name" : "Lorem ipsum", "body" : "Curabitur pretium tincidunt lacus." }` -- regex tools cannot keep track of the nesting structure, so they wouldn't be able to distinguish between the top-level `name` and `body` entries vs the ones under `previous_data`. But it's worse than that, because `sed` and `grep` work line-by-line, so depending on how the JSON is broken into lines, your script may get confused even just by that! – Gordon Davisson Jun 16 '20 at 18:02
  • Oh, and there's also the problem that quoted strings can contain things that look superficially like JSON syntax, but aren't. In principle, regex tools *can* handle this properly, but it's hard to get right and most people don't bother to even try. – Gordon Davisson Jun 16 '20 at 18:12
  • Thank you, Gordon. I got the point! – Amy Jun 17 '20 at 06:35

1 Answers1

2

If you really must use the shell approach (which has many pitfalls, really) AND your actual json input is not very different from what you have shown, this is my take. Read two fields, the key and value, and if the key matches, do something with the value.

while read -r key value; do
  case $key in
    ('"id":')   printf '%s\n' "id=${value%,}";;
    ('"body":') printf '%s\n' "body=${value%,}";;
  esac
done < json.txt

This will output

id=1
body="laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora"
Jens
  • 69,818
  • 15
  • 125
  • 179