简体   繁体   中英

nested json from text input using jq

I have text data which looks like (space separated snippet): First line is the header:

name type input file th repeatNumber
S1 class [12,7,6,19] sfile1 -10 2
S2 class [12,7,6,19] sfile2 -5 1
S3 bottom [12,7,16] sfile3 -15 1

Using shell script or command line (preferably using jq) want to convert this to one nested json which would look like:

'dets':{
       'S1':{
            'type':'class',
            'input': [12,7,6,19],
            'config':{
                    'file':'sfile1',
                     'th': -10
                    }
             },
        'S2':{
            'type':'class',
            'input': [12,7,6,19],
            'config':{
                    'file':'sfile2',
                     'th': -5
                    }
             },
        'S3':{
            'type':'bottom',
            'input': [12,7,16],
            'config':{
                    'file':'sfile3',
                     'th': -15
                    }
             }
        }

The appropriate approach to solving the problem using jq is essentially the same as would be used using awk : for each input line (except the first), parse it and emit the corresponding JSON object. For the sake of clarity, let's define a function for handling each of the input lines (read in as a string):

def parse:
  [splits(" +")]
  | {(.[0]) : {type: .[1],
               input: (.[2] | fromjson),
               config: { file: .[3],
                           th: .[4] }} };

The solution is then simply:

{ dets: [inputs | parse] | add }

The appropriate invocation of jq would look like this:

jq -R -f program.jq input.txt

Note that omitting the -n command-line option here has the effect of skipping the header line.

This invocation will produce the JSON shown below. Note that the text shown as JSON in the question is strictly speaking not JSON, but since the stated goal is to produce JSON, we'll leave it at that.

Caveats

The above solution makes various assumptions, notably:

1) the fields are "space-separated" in the sense of matching the regex " +"; in particular, it is assumed that the array is presented without any embedded spaces. 2) the "input" field can be parsed using fromjson ; if there is any doubt about that, then use (fromjson? // .) instead.

Output

{
  "dets": {
    "S1": {
      "type": "class",
      "input": [
        12,
        7,
        6,
        19
      ],
      "config": {
        "file": "sfile1",
        "th": "-10"
      }
    },
    "S2": {
      "type": "class",
      "input": [
        12,
        7,
        6,
        19
      ],
      "config": {
        "file": "sfile2",
        "th": "-5"
      }
    },
    "S3": {
      "type": "bottom",
      "input": [
        12,
        7,
        16
      ],
      "config": {
        "file": "sfile3",
        "th": "-15"
      }
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM