0

I am using a curl command to get json data from an application

the example curl response

{
    "count": 2,
    "value": [
        {
            "id": 344,
            "name": "ip-172-20-94-68",
            "status": "offline",
       
        },
        {
            "id": 345,
            "name": "ip-172-20-95-119",
            "status": "offline",
        }
    ]
}

My bash script

 ipAddresses=$(curl -s -X GET "$hostUrl" -u :"$EncodedPAT" | jq -r ".value[] | select(.status==\"offline\").name")
 ids=$(curl -s -X GET "$hostUrl" -u :"$EncodedPAT" | jq -r ".value[] | select(.status==\"offline\").id")

        for ipAddress in "${ipAddresses[@]}"
            do
                for id in "${ids[@]}"
                    do
                    echo "ipAddress: ${ipAddress} id: ${id}"
                done
        done

output

ipAddress: ip-172-20-94-68
ip-172-20-95-119
ip-172-20-95-113
ip-172-20-94-96
ip-172-20-94-86
id: 344
345
346
348
350

So it looks like it is only iterating through the outermost loop once, and not iterating through the inner loops (just uses first element).

expected output

ipAddress: ip-172-20-94-68 id: 344
ipAddress: ip-172-20-95-119 id: 345
ipAddress: ip-172-20-95-113 id: 346
ipAddress: ip-172-20-94-96 id: 348
ipAddress: ip-172-20-94-86 id: 350

I've looked elsewhere on the net but am having trouble finding anything relevant.

Any guesses as to what might be wrong?

freshGrad
  • 51
  • 5
  • A nested loop does exactly what you're seeing. You don't want that. Just loop once, by _index_. – Charles Duffy Nov 03 '22 at 11:38
  • Or -- here's a thought -- why not have just _one_ `jq` call give you pairs as its output? You'd also stop calling `curl` twice that way, and thus create less load on the server. – Charles Duffy Nov 03 '22 at 11:39
  • @CharlesDuffy thanks i have not thought of that im kinda new to jq – freshGrad Nov 03 '22 at 11:39
  • `while IFS=$'\t' read -r name id; do echo "IP address: $name; id: $id"; done < <(curl -s -X GET "$hostUrl" -u :"$EncodedPAT" | jq -r '.value[] | select(.status=="offline") | [.name, .id] | @tsv')` – Charles Duffy Nov 03 '22 at 11:41
  • (of course, if the only thing you're trying to do is generate the strings as output, that can be done just in jq alone with no shell loop at all: `curl -s -X GET "$hostUrl" -u :"$EncodedPAT" | jq -r '.value[] | select(.status=="offline") | "ipAddress: \(.name) id: \(.id)"'` – Charles Duffy Nov 03 '22 at 11:42
  • Since your `echo` is, according to the output you give here, executed exactly once, it means that the outer loop is executed once and during this execution the inner loop is also executed once. One obvious problem is that you access i.e. `ipAddresses` as if it were an **array**, but you define it as **scalar** (holding a single string). Perhaps you should also initialize it as array? – user1934428 Nov 03 '22 at 13:18

1 Answers1

2

You can combine this into a single call:

.value[] | select(.status == "offline") | "ipAddress: \(.name) id: \(.id)"

Gives:

"ipAddress: ip-172-20-94-68 id: 344"
"ipAddress: ip-172-20-95-119 id: 345"

Online JqPlay Demo

0stone0
  • 34,288
  • 4
  • 39
  • 64