5

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

    3 Answers 3

    10

    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]} 
    4
    • I have updated the question
      – meso_2600
      CommentedApr 29, 2015 at 9:21
    • @meso_2600: I updated the answer.
      – choroba
      CommentedApr 29, 2015 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
      CommentedMar 21, 2017 at 16:36
    • 1
      @t0r0X Use declare -g or declare -x within function to make it global/export.
      – Cromax
      CommentedFeb 6, 2018 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}" 

        You must log in to answer this question.

        Start asking to get answers

        Find the answer to your question by asking.

        Ask question

        Explore related questions

        See similar questions with these tags.