Explore Bash Variables with Dynamic Names

I'm trying to read from Bash variables for which I know the name suffixes, but I want to iterate over the prefixes.

Below is an example:

var1_name="variable1"
var1_size="2"
var2_name="variable2"
var2_size="3"
vars=(var1 var2)

for v in "${vars[@]}"
do
    echo $v_name
    echo $v_size
done

      

and I want the result to look like this:

variable1
2
variable2
3

      

Can this be done with Bash? I have tried with eval

and associative arrays, but I still cannot find a way to examine an already defined variable.

+3


source to share


2 answers


Below works for me. You first need to construct a variable and then evaluate it with an exclamation point.

var1_name="variable1"
var1_size="2"
var2_name="variable2"
var2_size="3"
vars=("var1" "var2")

for v in "${vars[@]}"
do
    name=${v}_name
    size=${v}_size
    echo ${!name}
    echo ${!size}
done

      



O / P

variable1
2
variable2
3

      

+3


source


auhuman's helpful answer solves your problem exactly as asked.

Here's an alternative that doesn't require you to first prefix the name in the array, assuming that all variables of interest have names with the same prefix, e.g . var

:



for name in "${!var@}"  # Loop over all variables whose names start with 'var'.
do
    [[ $name =~ ^var[0-9]+_(name|size)$ ]] || continue # Ignore unrelated names.
    echo "${!name}" # Use variable indirection to print the variable value. 
done

      

  • The code uses two forms of Bash's variable indirection , based on the syntax ${!...}

    :

    • "${!var@}"

      is a form of a literal-based list : it expands to a list (array) of names of all defined variables whose names have a literal prefix var

      (names start with var

      ), if any. Since before @

      only literal is allowed, using a template like "${!var[0-9]_@}"

      for a more complex match doesn't work unfortunately.

      • Example: for varName in "${!HOST@}"; do echo "$varName"; done


        gives HOSTNAME

        and HOSTTYPE

        eg.

      • The corresponding syntax ${!var*}

        (no double quotes) seems to work the same way.
        (Curiously, the page man

        claims that 1st char. Of is $IFS

        used to concatenate matching names, which will only work while waiting in a loop for

        if that 1st char. Is a char. Space. (Which is true for the $IFS

        default value that starts with space), but in practice a space is always used, regardless of the value $IFS

        , with (IFS=@; echo ${!HOST*})

        )

    • ${!name}

      , a variable-based scalar form , expands to the value of a variable whose name is stored as a value $name

      .

      • Example: var='value'; name='var'; echo ${!name}

        gives value

        .

      • Note. When using a trick (not used above), you can use an indirect expression for to get the values ​​of an array , namely by adding the all-indices [@]

        to the variable name to reference it indirectly; eg .:
        arr=( one two three ); name='arr[@]'; echo "${!name}"

        gives one two three

        ; accessing a specific element this way (for example name='arr[1]'

        ) also works, but retrieving a range of elements does not (for example name='arr[@]: 0:2'

        ).

    • There is also a form of array indices list - not used above - which expands to a list (array) of indices / keys of a given array / associative array.

      • Example: arr=( one two three ); echo "${!arr[@]}"


        gives 0 1 2

        , implicit sequential array indices.

      • It works similarly to explicitly assigned indices (for example
        arr=( [10]=one two three ); echo "${!arr[@]}"

        ) or, in Bash v4 +, with associative arrays (although, like the nature of associative arrays, keys cannot be listed in the order they were defined; for example
        declare -A aarr=( [one]=1 [two]=2 ); echo "${!aarr[@]}"

        ).

  • [[ $v =~ ^var[0-9]+_(name|size)$ ]]

    uses an operator =~

    to match a variable name with an extended regex in RHS to determine if it's an interesting name.

+2


source







All Articles