2

This has been asked several times, but none of the methods work. I would like to dynamically create arrays with array names taken from the variables. So lets start with just one array for now:

#!/bin/bash
i="aaa"
eval ${i}=("1")

results in

./1.sh: line 3: syntax error near unexpected token `('
./1.sh: line 3: `eval ${i}=("1")'

same result with:

$(eval ${i})=('1')
$(eval echo ${i})=('1')
$(eval "echo ${i}")=('1')

I do not want to eval everything, justthe array name. If it is possible I would like to avoid using eval at all

6

eval expects a string as the argument. You can't use ( unquoted, it has a special meaning in shell.

i=aaa
eval "$i=(1 2)"  # Use a string, $i will expand in double quotes.
echo ${aaa[1]})

You can also use declare or typeset instead of eval:

declare -a $i='(1 2)'

You still have to quote the parentheses and spaces.

To avoid eval completely, you can assign one by one:

#! /bin/bash
name=aaa
values=(1 2)
for ((i=0; i<${#values[@]}; ++i)) ; do
    read "$name[$i]" <<< "${values[i]}"
done
echo ${aaa[1]})
  • I have updated the question – meso_2600 Apr 29 '15 at 9:21
  • @meso_2600: I updated the answer. – choroba Apr 29 '15 at 9:34
  • The read variant is fantastic! At last a alternative to eval! The problem with declare/typeset is that in functions the declared variable is local to the function. – t0r0X Mar 21 '17 at 16:36
  • @t0r0X Use declare -g or declare -x within function to make it global/export. – Cromax Feb 6 '18 at 23:54
0

Here is a way to load the array without using eval. It doesn't use the ( data ) construct - instead it uses an input string with your choice of delimiter - the example uses |

i=aaa
IFS='|' read -a "$i" <<<"1|2   with spaces"
printf '%s\n' "${aaa[@]}"

Output:

1
2   with spaces
0

You can use declare with dynamic names and values, and variable indirection to reference variables based upon their name. printf '%q' can help you "shell-escape" values so that they can be used during dynamic assignments.

#!/bin/bash
declare -a products=( phone computer )
printf 'Product: %s\n' "${products[@]}"
# Product: phone
# Product: computer
unset products

declare varName='products'
declare -a "${varName}"='( cell\ phone laptop\ computer )'
declare arrayRef="${varName}[@]"
printf 'Product: %s\n' "${!arrayRef}"
# Product: cell phone
# Product: laptop computer
unset "${varName}"

declare -a toCopy=( 'LED TV' '"Smart" car' )
declare -a "${varName}"="( $( printf '%q ' "${toCopy[@]}" ) )"
printf 'Product: %s\n' "${!arrayRef}"
# Product: LED TV
# Product: "Smart" car
unset "${varName}"

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.