Variable expansion inside parentheses and quotes

In the script below, I can’t seem to make $var1 expand in the second statement. I’ve tried $var1, ${var1}, echo $var1 and '$var1'. It is inside a few sets of quotes and parentheses which I guess is what is causing the problem. Any ideas?

#!/bin/bash

# Get the AutoScalingGroupName for the NameNode ASG
var1=$(aws cloudformation list-stack-resources --stack-name abc123 | jq '.StackResourceSummaries[] | select(.ResourceType=="AWS::AutoScaling::AutoScalingGroup")' | jq '.PhysicalResourceId' | tr -d '"' | grep nn); echo $var1

var2=$(aws autoscaling describe-auto-scaling-instances | jq -r '.AutoScalingInstances[] | select(.AutoScalingGroupName == "$var1") | select(.AvailabilityZone == "us-east-1a") .InstanceId'); echo $var2
Asked By: Sco

||

Variables in single quotes are not expanded. Try this…

var2=$(aws autoscaling describe-auto-scaling-instances | jq -r '.AutoScalingInstances[] | select(.AutoScalingGroupName == "'"$var1"'") | select(.AvailabilityZone == "us-east-1a") .InstanceId'); echo $var2
Answered By: yaegashi

It is wrapped in single-quotes, so it cannot be expanded.

jq -r '.AutoScalingInstances[] | select(.AutoScalingGroupName == "$var1") ... .InstanceId'

The key part is the jq command that you are actually only passing a single argument to (notice the long red part of the command). So your pipes are also not taking effect. You can selectively wrap things in quotes that truly need to be.

Answered By: Micah Elliott

Shell variables are not expanded within single quotes.

In this case, you don’t really want to inject the the var1 shell variable in the jq expression without first encoding it as a JSON string though, which is what you do with the --arg option to the utility:

jq --arg name "$var1" '... | select(.AutoScalingGroupName == $name) ...'

This way, you create a jq variable called name with the JSON-encoded string from the var1 shell variable.

Your full script may written like this (also simplifying the other bits of code):

#!/bin/sh

resourceId=$(
    aws cloudformation list-stack-resources --stack-name abc123 |
    jq -r '
        .StackResourceSummaries[] |
        select(.ResourceType == "AWS::AutoScaling::AutoScalingGroup").PhysicalResourceId |
        select(contains("nn"))'
)

instanceId=$(
    aws autoscaling describe-auto-scaling-instances |
    jq -r --arg name "$resourceId" '
        .AutoScalingInstances[] |
        select(
            .AutoScalingGroupName == $name and 
            .AvailabilityZone == "us-east-1a"
        ).InstanceId'
)

printf 'instanceId = "%s"n' "$instanceId"
Answered By: Kusalananda