2

How do I use dynamic array variable names in bash?

numCounter=1
arrayIndex=0

arr$numCounter[$arrayIndex]=0
((arrayIndex++))
arr$numCounter[$arrayIndex]=1

What I'm hoping this will return is

arr1[0] is 0
arr1[1] is 1

What I want to do is have n number of arrays and store x number of files in each array.

var1=1
arrayFolder(var1)[index0] = file1
arrayFolder(var1)[index1] = file2
arrayFolder(var1)[index2] = file3

var1=2  
arrayFolder(var1)[index0] = file4
arrayFolder(var1)[index1] = file5
arrayFolder(var1)[index2] = file6

Expected result
arrayFolder1[0]=file1
arrayFolder1[1]=file2
arrayFolder1[2]=file3
arrayFolder2[0]=file4
arrayFolder2[1]=file5
arrayFolder2[2]=file6

How can I achieve this?

4
  • Didn't you ask this and get a duplicate question pointer very recently? It would do some good to show how you tried to apply that answer, and how that failed. Commented Feb 12, 2018 at 17:07
  • declare "arr$numCounter[$arrayIndex]"=0; ((arrayIndex++)); declare "arr$numCounter[$arrayIndex]"=1 should work Commented Feb 12, 2018 at 17:09
  • (...ahh, assign to a bash array indirectly by dynamically constructed variable is the answer I closed your prior question with. This one is much better asked than your prior question yesterday -- and thank you for putting in the effort; since you've put in that effort, I'm assuming you also have a distinct and unique question, but it's still not obvious to me where this question isn't covered by the prior one; could you edit to make that more explicit?) Commented Feb 12, 2018 at 17:15
  • (To be clear -- this is sufficiently well-asked that if even if it does end up getting closed as dupe, I'd ask you not to delete it -- good duplicates add value to the site insofar as they set up additional search terms that direct someone to whichever question we've decided is the canonical instance). Commented Feb 12, 2018 at 17:29

3 Answers 3

5

Using bash 4.3, declare -n aliasName=destVarName will make aliasName refer to destVarName, even for arrays; thus permitting any kinds of assignment, dereferencing, &c. you would otherwise use.

#!/usr/bin/env bash
#          ^^^^^^^^ - Use bash version from PATH; on MacOS, this should be newer
#                     than the system one if MacPorts, Homebrew, etc. is installed.

case $BASH_VERSION in
  ''|[1-3]*|4.[0-2]*) echo "This code requires bash 4.3 or newer" >&2; exit 1;;
esac

# to make "index0", "index1", &c. valid indexes, our arrays need to be associative
declare -A arrayFolder1 arrayFolder2

var1=1
declare -n curArrayFolder=arrayFolder$var1
curArrayFolder[index0]=file1
curArrayFolder[index1]=file2
curArrayFolder[index2]=file3
unset -n curArrayFolder

var1=2  
declare -n curArrayFolder=arrayFolder$var1
curArrayFolder[index0]=file4
curArrayFolder[index1]=file5
curArrayFolder[index2]=file6
unset -n curArrayFolder

...will properly result in a situation where:

declare -p arrayFolder1 arrayFolder2

emits as output:

declare -A arrayFolder1=([index0]="file1" [index1]="file2" [index2]="file3" )
declare -A arrayFolder2=([index0]="file4" [index1]="file5" [index2]="file6" )

If you want to try to cut down the number of commands needed to switch over which folder is current, consider a function:

setCurArrayFolder() {
  declare -p curArrayFolder &>/dev/null && unset -n curArray
  declare -g -n curArrayFolder="arrayFolder$1"
  var1=$1
}

Then the code becomes:

setCurArrayFolder 1
curArrayFolder[index0]=file1
curArrayFolder[index1]=file2
curArrayFolder[index2]=file3

setCurArrayFolder 2
curArrayFolder[index0]=file4
curArrayFolder[index1]=file5
curArrayFolder[index2]=file6
Sign up to request clarification or add additional context in comments.

3 Comments

I was missing the declare -A and unset. How can I read the array? I tried echo ${curArrayFolder1[0]} and echo ${arrayFolder1[0]} and there's no value associated with it.
In the above examples, it's actually ${curArrayFolder1[index0]} where the value is set, as opposed to ${curArrayFolder1[0]} (since "index0" was the example you used in the question). declare -A isn't essential to indirect array assignment, but it is essential to be able to have non-numeric array indices, such as index0 instead of 0.
I'm using a variable for array indexes. Numeric array indices seems to work. Thanks this worked.
0

You can use declare and variable indirection.

#!/bin/bash
numCounter=1
arrayIndex=0

assign () {
    sub="sub$1[$2]"
    declare -g $sub=$3
}

get () {
    r="sub$1[$2]"
    echo "${!r}"
}

assign $numCounter $arrayIndex 0

((arrayIndex++))
assign $numCounter $arrayIndex 1

((numCounter++))
assign $numCounter 0 2

echo $(get 1 0) is 0
echo $(get 1 1) is 1
echo $(get 2 0) is 2

Comments

0

A multidimensional array can be emulated by using an associative array with multiple values concatenated into each key. You could, for instance, join two numbers with a colon ,:

declare -A arrayFolder

var1=1
arrayFolder[$var1,$index0]=file1
arrayFolder[$var1,$index1]=file2
arrayFolder[$var1,$index2]=file3

var1=2  
arrayFolder[$var1,$index0]=file4
arrayFolder[$var1,$index1]=file5
arrayFolder[$var1,$index2]=file6

Result:

$ declare -p arrayFolder
declare -A arrayFolder='([2,0]="file4" [2,1]="file5" [2,2]="file6" [1,2]="file3" [1,1]="file2" [1,0]="file1" )'

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.