1

Like this: I have a json file with below format:

{
    "Item": {
        "summary": {
            "B": "ABCDE"
        },
        "name": {
            "S": "sider"
        },
        "age": {
            "N": "1"
        },
        "data": {
            "B": "abcde"
        }
    }
}

How can I get the object "Item" only using existed commands like sed/awk without installing any external tools in shell?

expected output:

{
    "summary": {
        "B": "ABCDE"
    },
    "name": {
        "S": "sider"
    },
    "age": {
        "N": "1"
    },
    "data": {
        "B": "abcde"
    }
}
4
  • 2
    Don't. Do you try to compile C code with only sed or awk? Do you try to manipulate image files with only sed or awk? Use the right tool for the job, and using line-oriented, regular-expression-based tools are not appropriate for a non-regular structured language like JSON. Commented Feb 15, 2020 at 13:39
  • Get a proper tool for working with JSON; don't let design decisions based on 40-year-old assumptions dictate how you work with modern data. Commented Feb 15, 2020 at 13:40
  • 2
    If grep '^[[:space:]]' file isn't all you need then edit your question to better specify your requirements and maybe also provide more truly representative sample input/output. Also add what you've tried so far. Commented Feb 15, 2020 at 14:46
  • care to define what you mean by get the object "Item"? are you looking for any particular (output) format? or perhaps update the question with what you're expecting to see as the output? while we're at it, are you expecting all input to be nicely formatted as in your example? Commented Feb 15, 2020 at 15:40

3 Answers 3

2

As chepner suggests, you need to question your constraints. In some cases, you are dealt a bad hand and have to deal with it. So here is a sed approach:

Here's a revised solution with awk. Sed is thrown in also to un-indent:

awk '  
  /^    }/  { p = 0 ; print  }  
  p == 1 { print } 
  /"Item": {/ { print "   {" ; p = 1 }  
'  | sed 's/^   //'

Originally posted this (but noticed that the output didn't match your expectations):

sed -n '/^    "Item": {/,/^    }/p'

The above sed approach assumes that Item is indented as you have it in the sample input above.

Here's an approach using my favorite, jq:

jq '.Item'

You may do well to check if python with the json package is installed on your machine. Here's a python3 script that would suit your needs:

#!/usr/bin/env python3

import json
import sys
j = json.load( sys.stdin ) 
print(json.dumps(j["Item"]))
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @Mark, that's almost what I want besides a single difference: I got some extra spaces in output json after awk&sed in your first answer.
awk ' /^ }/ { p = 0 ; print } p == 1 { print } /"Item": {/ { print "{" ; p = 1 } ' | sed 's/^ //' Is this more appropriate?
I prefer the awk/sed answer to just the sed answer since it is more correct - the "Item" tag is printed with the sed only answer. As long as you receive very well formatted input, it should continue to work for you. Ultimately, it's not a general solution since many inputs will break it.
1

Idiomatically, it'd be incorrect to manipulate a nested data format like JSON with line-aware tools like sed/awk. However if you're limited in your choice, then the best approach is following:

  1. convert multi-line file to a single line
  2. using awk/sed extract your Item

Here's a sed based solution:

bash $ <file.json tr '\n' ' ' | sed -E 's/^ *{ *"Item": +//; s/ *}$//'

2 Comments

Thanks @Dmitry, but I got a sed: -e expression #1, char 18: Invalid preceding regular expression in output then.
you must be on linux - the solution of mine is good for MacOS. For linux then, you'd need to quote the opening brace, like this: <file.json tr '\n' ' ' | sed -E 's/^ *\{ *"Item": +//' | sed -E 's/ *}$//'
0

This is what you need:

sed -n '/^    "Item": {/,/^    }/{s/"Item": //;s/^    //;p}'

which essentially build upon Mark's solution by making two substitutions to remove "Item": and de-indent 4 spaces before printing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.