Home > other >  Can't assign multiple values to 3 variables
Can't assign multiple values to 3 variables

Time:11-11

Request

curl -XGET http\://my_host\:9111/api/issues/search\?componentKeys\=my_poject\&facets\=severities\&p\=1\&ps\=1

Here response:

{
  "total": 10057,
  "p": 1,
  "ps": 1,
  "paging": {
    "pageIndex": 1,
    "pageSize": 1,
    "total": 10057
  },
  "effortTotal": 51031,
  "issues": [
    {
      "key": "AX0NVCNfENszTAxEgX5e",
      "rule": "java:S122",
      "severity": "MINOR",
      "component": "my_project:SomeFile.java",
      "project": "my_project",
      "line": 241,
      "hash": "1111111111",
      "textRange": {
        "startLine": 241,
        "endLine": 241,
        "startOffset": 0,
        "endOffset": 46
      },
      "flows": [],
      "status": "OPEN",
      "message": "At most one statement is allowed per line, but 2 statements were found on this line.",
      "effort": "1min",
      "debt": "1min",
      "author": "eugeniur",
      "tags": [
        "convention"
      ],
      "creationDate": "2021-11-11T06:40:05 0200",
      "updateDate": "2021-11-11T06:40:05 0200",
      "type": "CODE_SMELL",
      "scope": "MAIN"
    }
  ],
  "components": [
    {
      "key": "my_project",
      "enabled": true,
      "qualifier": "TRK",
      "name": "Parent",
      "longName": "Parent"
    },
    {
      "key": "my_project:MyFile.java",
      "enabled": true,
      "qualifier": "FIL",
      "name": "XStartDServerComponent.java",
      "longName": "MyFile.java",
      "path": "MyFile.java"
    }
  ],
  "facets": [
    {
      "property": "severities",
      "values": [
        {
          "val": "CRITICAL",
          "count": 5818
        },
        {
          "val": "MAJOR",
          "count": 1459
        },
        {
          "val": "BLOCKER",
          "count": 1286
        },
        {
          "val": "MINOR",
          "count": 1163
        },
        {
          "val": "INFO",
          "count": 331
        }
      ]
    }
  ]
}

Now I want to extract keys: "total", "issues", "facets.values".

So I try this in my bash script:

#!/bin/bash
readonly BASE_URL=http://my_host:9111/api
readonly PROJECT_KEY=my_project

read totalIssues facetsArr issuesArr < <(echo $(curl -XGET $BASE_URL/issues/search\?componentKeys\=$PROJECT_KEY\&facets\=severities\&p\=1\&ps\=1 |
                       jq -r '.total, .issues[], .facets[].values'))
echo "total      : $totalIssues"
echo "facetsArr     : $facetsArr"
echo "issuesArr  : $issuesArr"

But result is:

total      : 10057
facetsArr  : {
issuesArr  : "key": "AX0NVCNfENszTAxEgX5e", "rule": "java:S122", "severity": "MINOR", "component": "MyFile.java", "project": "myProject", "line": 241, "hash": "b68d3b4b390c81e2714d263b31acdd08", "textRange": { "startLine": 241, "endLine": 241, "startOffset": 0, "endOffset": 46 }, "flows": [], "status": "OPEN", "message": "At most one statement is allowed per line, but 2 statements were found on this line.", "effort": "1min", "debt": "1min", "author": "eugeniur", "tags": [ "convention" ], "creationDate": "2021-11-11T06:40:05 0200", "updateDate": "2021-11-11T06:40:05 0200", "type": "CODE_SMELL", "scope": "MAIN" } [ { "val": "CRITICAL", "count": 5818 }, { "val": "MAJOR", "count": 1459 }, { "val": "BLOCKER", "count": 1286 }, { "val": "MINOR", "count": 1163 }, { "val": "INFO", "count": 331 } ]

Why "facetsArr" get incorrect value?

The "facetsArr" must be:

facetsArr  : [ { "val": "CRITICAL", "count": 5818 }, { "val": "MAJOR", "count": 1459 }, { "val": "BLOCKER", "count": 1286 }, { "val": "MINOR", "count": 1163 }, { "val": "INFO", "count": 331 } ]

CodePudding user response:

  1. Use string manipulation to insert a newline (\n) between each value, each line will now contain the value you're trying to catch
  2. Quote the jq command since it may contain spaces [info]
  3. Set IFS to a newline [info]
  4. Use read -d '' [docs]

    -d delim

    continue until the first character of DELIM is read, rather than newline


Applying those fixes, the script will look like:

IFS=$'\n'
read -r -d '' totalIssues facetsArr issuesArr <<< "$( jq -r '"\(.total)\n\(.facets[].values)\n\(.issues[])"' input)"
echo "total      : $totalIssues"
echo "facetsArr  : $facetsArr"
echo "issuesArr  : $issuesArr"

Note: I've replaced the curl command with an actual file called input containing OP's JSON


The output will be:

total      : 10057
facetsArr  : [{"val":"CRITICAL","count":5818},{"val":"MAJOR","count":1459},{"val":"BLOCKER","count":1286},{"val":"MINOR","count":1163},{"val":"INFO","count":331}]
issuesArr  : {"key":"AX0NVCNfENszTAxEgX5e","rule":"java:S122","severity":"MINOR","component":"my_project:SomeFile.java","project":"my_project","line":241,"hash":"1111111111","textRange":{"startLine":241,"endLine":241,"startOffset":0,"endOffset":46},"flows":[],"status":"OPEN","message":"At most one statement is allowed per line, but 2 statements were found on this line.","effort":"1min","debt":"1min","author":"eugeniur","tags":["convention"],"creationDate":"2021-11-11T06:40:05 0200","updateDate":"2021-11-11T06:40:05 0200","type":"CODE_SMELL","scope":"MAIN"}

CodePudding user response:

Slightly inefficient, but it would be much simpler to just parse the (small) response 3 times.

#!/bin/bash
readonly BASE_URL=http://my_host:9111/api
readonly PROJECT_KEY=my_project

response=$(curl -XGET "$BASE_URL/issues/search?componentKeys=$PROJECT_KEY&facets=severities&p=1&ps=1")

total=$(jq '.total' <<< "$response")
issues=$(jq '.issues' <<< "$response")
facets=$(jq '.facets[].values' <<< "$response")

# ...

Then you don't have to worry about constructing a single output with jq that bash must parse anyway.

(I've intentionally left the value of issues a JSON array, rather than a stream of issues, in the event that there is more than a single object in the array.)

  • Related