Examine Bash variables with dynamic names

最后都变了- 提交于 2021-02-07 20:23:53

问题


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

I give an example below:

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'd want the output to look like follows:

variable1
2
variable2
3

Is there any to do this with Bash? I have tried with eval and associative arrays, but I still can't find a way to examine an already defined variable.


回答1:


Below works for me. You need to construct the variable first and then evaluate it using exclamation.

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



回答2:


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

Here's an alternative that doesn't require you to specify the name prefixes in an array first, assuming that all variables of interest have names with the same prefix, such as 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's value. 
done
  • The code uses two forms of Bash variable indirection, all based on syntax ${!...}:

    • "${!var@}" is the literal-based list form: it expands to the list (array) of the names of all defined variables whose names have literal prefix var (whose names start with var), if any. Since only a literal is allowed to precede @, using a pattern such as
      "${!var[0-9]_@}" for more sophisticated matching does not work, unfortunately.

      • Example: for varName in "${!HOST@}"; do echo "$varName"; done
        yields HOSTNAME and HOSTTYPE, for instance.

      • The related ${!var*} syntax (without double quotes) seems to work the same.
        (Curiously, the man page claims that the 1st char. of the $IFS value is used to concatenate the matching names, which would only work as expected in a for loop if that 1st char. is a whitespace char. (which is true of the $IFS default value, which starts with a space), but in practice a space is always used, irrespective of the value of $IFS; verify with (IFS=@; echo ${!HOST*}))

    • ${!name}, the variable-based scalar form, expands to the value of the variable whose name is stored as the value of $name.

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

      • Note: With a trick (not used above), you can use indirection to get an array's values too, namely by appending the all-indices index expression [@] to the name of the variable to reference indirectly; e.g.:
        arr=( one two three ); name='arr[@]'; echo "${!name}" yields one two three; accessing a specific element this way (e.g., name='arr[1]') works too, but extracting a range of elements does not (e.g., name='arr[@]: 0:2').

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

      • Example: arr=( one two three ); echo "${!arr[@]}"
        yields 0 1 2, the implicit sequential indices of the array.

      • It works analogously with explicitly assigned indices (e.g.,
        arr=( [10]=one two three ); echo "${!arr[@]}") or, in Bash v4+, with associative arrays (although, as is the nature of associative arrays, the keys are not guaranteed to be listed in the order they were defined; e.g.,
        declare -A aarr=( [one]=1 [two]=2 ); echo "${!aarr[@]}").

  • [[ $v =~ ^var[0-9]+_(name|size)$ ]] uses the =~ operator to match the variable name at hand against the extended regular expression on the RHS to determine if it is a name of interest.



来源:https://stackoverflow.com/questions/43306880/examine-bash-variables-with-dynamic-names

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!