Revell
Revell

Reputation: 723

Best way to parse JSON-like file using awk/sed

I have a file which contents are like the following:

{application_name, [
    {settings, [
        {generic_1, [
            {key_1, "value"},
            {key_2, 1},
            {key_3, [something, other]}
        ]},
        {generic_2, [
            {key_1, "value"},
            {key_3, [something, other]}
        ]},
        {{generic_2, specific_1}, [
            {key_3, [entirely, different]}
        ]},
    ]}
]}

Now I'm looking for a way to parse this using awk or sed (or something else). What I need is to be able to specify a key, and then get the "blockname" returned.

f.e. if I want all settings for key_3 returned as follows:

generic_1 [something, other]
generic_2 [something, other]
specific_1 [entirely, different]

What would be the best way to approach this?

Upvotes: 1

Views: 2337

Answers (2)

Jotne
Jotne

Reputation: 41456

I do agree with Etan that this is a job for another tools.
This is an gnu awk approach (due to multiple characters in RS), not a complete solution.

awk -v RS="generic_[0-9]" 'NR==1 {f=RT;next} {$1=$1;n=split($0,a,"[][]");if (a[1]~/}/) {split(a[1],b,"[ }]");f=b[2]};printf "%s [",f;for (i=1;i<=n;i++) if (a[i]~/key_3/) print a[i+1]"]";f=RT}' file
generic_1 [something, other]
generic_2 [something, other]
specific_1 [entirely, different]

Or some more readable:

awk -v RS="generic_[0-9]" '
NR==1 {
    f=RT
    next} 
    {
    $1=$1
    n=split($0,a,"[][]")
    if (a[1]~/}/) {
        split(a[1],b,"[ }]")
        f=b[2]}
    printf "%s [",f
    for (i=1;i<=n;i++)
        if (a[i]~/key_3/)
            print a[i+1]"]"
            f=RT
    }' file

Upvotes: 0

Etan Reisner
Etan Reisner

Reputation: 80931

The best solution for how to parse JSON data with sed or awk is... not to do that with sed or awk. They aren't designed for it.

Use a tool that understands JSON like

  1. perl
  2. python
  3. ruby
  4. javascript
  5. jq
  6. Just about anything else

Using anything like sed or awk on this is going to be fragile (at best).

Upvotes: 8

Related Questions