3

How do i add a variable as the name of the variable i want to checks value. My code is as below, when i run this i get the error:

[: A_variable: integer expression expected

I think this is because when doing an if on a variable the proper syntax should be: if [ $A_variable -eq 1 ]; but i am not able to put the dolla sign in front of my variable because i am putting a different variable in the value of my variable.

Its almost like it should be: if [ $${letter}_variable or some mix of this but i dont know what?

array=("A" "B" "C")

A_variable=1
B_variable=2
for letter in "${array[@]}"
do

if [ ${letter}_variable -eq 1 ]; then
...
a.smith
  • 705
  • 4
  • 13
  • 28
  • You would probably be better off using an associative array, instead of a bunch of similarly named but independent variables. See e.g. [my older answer to a similar question](https://unix.stackexchange.com/a/413455/170373) and the [section on them in BashFAQ](http://mywiki.wooledge.org/BashFAQ/006#Associative_Arrays). – ilkkachu Sep 20 '19 at 14:28

3 Answers3

6

This is called indirect expansion in bash.

The syntax to get the value of a variable whose name is determined by another variable namevar is:

${!namevar}

Since your variable name is composed of a variable and a constant string, you'll need one intermediate step:

array=("A" "B" "C")

A_variable=1
B_variable=2
for letter in "${array[@]}"
do
    varname="${letter}_variable"
    if [ "${!varname}" -eq 1 ]; then
    ...

Note: if the indirectly-referenced variable does not actually exist, the expansion will result in a null string, which will still cause an error. If this is not desirable, add a second test like this first:

    varname="${letter}_variable"
    if [ "${!varname}" = "" ]; then
        echo "Error: $varname is non-existent or empty"
    elif [ "${!varname}" -eq 1 ]; then
    ...

Also, using double quotes to protect against unexpected characters in the expansion result would be a good idea, if the contents of all the possible matching variables are not initialized to safe values in advance.

telcoM
  • 87,318
  • 3
  • 112
  • 232
  • This will still throw an error for "C": `[: : integer expression expected` – markgraf Sep 20 '19 at 13:09
  • Well, yes... because in the OP's original setup, `array` has three elements, `A`, `B` and `C`, and only two of the variables resulting from the expansion have been initialized. I understood the core of the question was about the indirect expansion, and the OP did not indicate what they want to happen if the indirect-referenced variable does not exist. – telcoM Sep 20 '19 at 13:21
1

You are comparing a string ("A_variable") to an integer ("1").

You can get around this issue by using declare -n. From help declare:

-n make NAME a reference to the variable named by its value

We need [[ .. ]] to avoid the error the unset "C_variable" is causing.

#!/bin/bash
array=("A" "B" "C")

A_variable=1
B_variable=2
for letter in "${array[@]}"
do
  declare -n foo="${letter}_variable"
  if [[ "$foo" -eq 1 ]]; then
    echo "Ding"
  fi
done

Bonus: you can declare -i A_variable=1 to make it an integer.

-i to make NAMEs have the `integer' attribute

markgraf
  • 2,849
  • 1
  • 8
  • 20
0

The operator -eq is for math expressions, but you are comparing strings.

To campare strings use =.

schrodingerscatcuriosity
  • 12,087
  • 3
  • 29
  • 57