I know you can create an indirect parameter expansion to an array like so:
var1=\"target\"
var2=\"arrayname\"
targetarrayname=( \"one\" \"two\" \"three\" )
b
It avoids substantial security bugs to run all values through printf %q
to ensure that they're safely escaped before substituting them into eval
content.
#!/bin/bash
appendToArray() {
local _targetArrayName _argumentData _cmd
_targetArrayName=$1; shift || return
printf -v _argumentData '%q ' "$@"
printf -v _cmd '%q+=( %s )' "$_targetArrayName" "$_argumentData"
eval "$_cmd"
}
target=( "first item" "second item" )
appendToArray target "third item" "fourth item"
declare -p target
...correctly emits as output:
declare -a target=([0]="first item" [1]="second item" [2]="third item" [3]="fourth item")
#!/bin/bash
appendToArray() {
declare -n _targetArray=$1; shift
_targetArray+=( "$@" )
}
target=( "first item" "second item" )
appendToArray target "third item" "fourth item"
declare -p target
...has identical output, with much less (and much simpler) code.
#!/bin/bash
var1="target"
var2="arrayname"
targetarrayname=( "one" "two" "three" )
builtarrayname="${var1}${var2}[@]"
echo ${!builtarrayname} # prints "one two three"
eval "${builtarrayname:0:-3}+=( 'foo' )"
echo ${!builtarrayname} # prints "one two three foo"
Do note though that eval could be considered evil :p You need to be sure that you only have sanitized input to eval statements, to avoid the possibility of unintended code execution.
EDIT:
The :0:-3
in eval "${builtarrayname:0:-3}+=( 'foo' )"
removes [@]
from the literal string that $builtarrayname
contains. Since assignment of arrays only use the variable name, we had to remove it. ( read more here to see how string manipulation in variables work )
and no, I don't think it can be done without eval, as that's how the left side of the assignment gets resolved before the assignment occurs (see this nice answer for more info on eval.
You can do it with printf
arrayname=()
arrayvariable=arrayname
printf -v $arrayvariable[1] "test"
echo "${arrayname[1]}"
To fill in whole array you can use a for loop
arrayname=()
arrayvariable=arrayname
for i in {0..5}; {
item="$arrayvariable[$i]"
printf -v $item "test$i"
echo "${!item}"
}
Note that quotes are not necessary around var name in printf
command because var name can't have spaces, if you try to add var with space in name it'll give you this error
$ printf -v 'test 1' 'sef'
bash: printf: `test 1': not a valid identifier
The declare
command takes assignments as arguments, which are expanded before the declaration. Thus, you can introduce any level of indirection when declaring variables. The following works in Bash 3.2.
$ array=myarray
$ declare -a "$array+=(\"element 1\")"
$ echo ${myarray[0]}
element 1