I have a bash script which contains awscli as well. I am trying to print a variable which is created in a for loop. The variable that I am trying to print contains $ sign because of for loop. I couldn't print the value. Below I am sharing the script. The output of this script is only numbers which is generated in the for loop. I want to print the value which is generated in the command.


declare -i counter=11
declare -i counter2=14

for i in {1..2}
    declare v1$i=$(aws iam get-group --group-name VideoEditors | awk -v counter1=$counter 'NR==counter1' | awk -F\" '{print $4}') 


    declare v2$i=$(aws iam get-group --group-name VideoEditors | awk -v counter3=$counter2 'NR==counter3' | awk -F\" '{print $4}')

    echo $v1$i
    echo $v2$i
  • 1
    Use "${var}" instead of just $var; ${x}${y} instead of $x$y. See unix.stackexchange.com/questions/4899/… – Kenneth B. Jensen Feb 8 '19 at 6:57
  • 2
    I don't see any way that the braces would make a lick of difference there. – Michael Homer Feb 8 '19 at 7:07
  • Kenneth, I tried your solution but result is the same. The output is: taskscript.sh: line 16: ${v1$i}: bad substitution – user335832 Feb 8 '19 at 7:18
  • @MichaelHomer I've performed several more tests; turns out that I was printing just $y, which was identical to $x$y. OP, my advice would be to use an array for v1 and v2 instead of v11/v12/v21/v22/etc. – Kenneth B. Jensen Feb 8 '19 at 7:20
  • 1
    @Kusalananda, the addition works since they're declared integer variables. Even counter+=7 would do. Though I'm not sure if it would be more readable to just use $(( .. )) with regular variables ... – ilkkachu Feb 8 '19 at 8:52

Use an array instead, that allows you to properly index the variables:


declare -ai counters=(11 14)        # indexes start from 0

for i in {1..2}; do
    v1[$i]=$(aws iam get-group --group-name VideoEditors | awk -v counter1="$counter" 'NR==counter1' | awk -F\" '{print $4}') 

    v2[$i]=$(aws iam get-group --group-name VideoEditors | awk -v counter3="$counter2" 'NR==counter3' | awk -F\" '{print $4}')

    echo "${v1[$i]}"
    echo "${v2[$i]}"

You could probably put the vN assignments within another for loop to reduce the repetition.

Of course, if you're not using v1 and v2 for anything other than displaying the values once, you could just run aws ... | awk directly and skip the variables and the echo.

| improve this answer | |

I don't know what your code is supposed to accomplish but what it does is this:

In the first iteration - when i equals 1 - it declares variables v11 and v12 and assigns something to them and then prints $v1$i to the screen.

v1 is non-existent and $i is the value of i, so you should get 'nothing' with an appended 1 as output in the first loop:

And then in the second iteration - when i equals 2 - two times 2 for the same reason.

What you do after the equal sign with awk etc. is irrelevant for the outcome.

The suggestion to use an array and use $i as an index into it will solve the problem.

| improve this answer | |

You seem to want to output the fourth "-delimited field on lines 11, 17, 18, and 21 of the output of an aws command.

aws iam get-group --group-name VideoEditors |
awk -F '"' 'NR == 11 || NR == 17 || NR == 18 || NR == 21 { print $4 }'

This calls aws once instead of four times, and calls awk once instead of eight times.

If you want this in an array:

readarray -t output < <(
aws iam get-group --group-name VideoEditors |
awk -F '"' 'NR == 11 || NR == 17 || NR == 18 || NR == 21 { print $4 }' )

The array output would now contain the data with one line from awk in each element, starting at index 0.

If you want to split that array into two, so that you get element 0 and 2 in one and 1 and 3 in the other:

v1=( "${output[0]}" "${output[2]}" )
v2=( "${output[1]}" "${output[3]}" )
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.