Pipe aws output to jq will not result in array

30 views Asked by At

I try to use to get all hosts from an elbv2 LoadBalancer rule to an array to expand the list. I tried to query the existing hosts inside the rule with

TESTOUTPUT=$(aws elbv2 describe-rules --rule-arns arn:aws:elasticloadbalancing:ap-northeast-1:xxxx:listener-rule/app/k8s-ctrlroute-xxx/xxx/xxx --region ap-northeast-1 --no-cli-pager)

works great, I get the JSON with the hosts back. No I try to parse the output direct to an Array with

TESTOUTPUT=$(aws elbv2 describe-rules --rule-arns arn:aws:elasticloadbalancing:ap-northeast-1:xxxx:listener-rule/app/k8s-ctrlroute-xxx/xxx/xxx --region ap-northeast-1 --no-cli-pager | jq [.Rules[0].Conditions[0].Values[]])

The result are the expected hosts. It looks like

[ "host1.cloud", "host2.cloud", "host3.cloud" ]

But if I not try to add an entry with TESTOUTPUT+="host4.cloud" I will get

[ "host1.cloud", "host2.cloud", "host3.cloud" ]host4.cloud

So I assume the expected array is not an array. But the jq output is the syntax for array output. Maybe someone can borrow me two eyes for a different view on the case to find out what is wrong in my code.

2

There are 2 answers

1
tripleee On

Because that's still just a string, albeit a string which would represent a valid JSON array if you gave it to a JSON parser; but Bash is not one.

If you want to get the output in a Bash array, try

testoutput=($(aws elbv2 describe-rules \
    --rule-arns arn:aws:elasticloadbalancing:ap-northeast-1:xxxx:listener-rule/app/k8s-ctrlroute-xxx/xxx/xxx \
    --region ap-northeast-1 --no-cli-pager |
  jq '[.Rules[0].Conditions[0].Values[]] | @sh'))

The crucial changes are

  • parentheses around the value to actually assign to an array, not a string scalar
  • adding the | @sh decorator to the jq expression

Also, for good measure, single-quote the jq expression; and add backslash line wraps to untangle the horrendously long command line.

The next inevitable question if you are unfamiliar with Bash arrays is, "how do I examine the array?"

printf '%s\n' "${testoutput[@]}"

to print all of it, or

for value in "${testoutput[@]}"; do
    : something with "$value"
done

to loop over them individually.

Beginners tend to try

echo "$testoutput"

(even without the quotes, for a true beginner) and be flabbergasted when it only prints the first element.

Tangentially also don't use upper case for your private variables.

0
erik258 On

jq speaks json, but most programs do not. If you want to manipulate json, you'll want to do it with jq.

 echo '{"Rules": [ { "Conditions":[ { "Values": [ "host1.cloud", "host2.cloud", "host3.cloud" ] } ] } ] }' \
|jq '.Rules[0].Conditions[0].Values += ["host4.cloud"]'
{
  "Rules": [
    {
      "Conditions": [
        {
          "Values": [
            "host1.cloud",
            "host2.cloud",
            "host3.cloud",
            "host4.cloud"
          ]
        }
      ]
    }
  ]
}