Reputation: 31
I've got about 10 arrays like so:
array_1=("Mike" "George" "Sam" "1234" "5678")
array_2=("Albert" "Isabel" "Sami" "4567" "9821")
array_3=("Michel" "Tom" "Cathy" "321" "5664")
array_4=("name 1" "name 2" "name 3" "1233" "4567")
array_5=...
To get single array elements (this is needed because not all are used in the script):
name1="${array_1[0]}"
name2="${array_1[1]}"
name3="${array_1[2]}"
number1="${array_1[3]}"
number2="${array_1[4]}"
Sometimes I want to use array_2 (or 3/4..) instead of array_1. To avoid replacing (array_1) in all the lines of the names and numbers, I'm looking to use a simple variable substitution, so tried to replace with different kind of quotes, including:
myarray="array_1" // also tried 'array_1' and $array_1
name1="${myarray[0]}" // also tried "${$!myarray[0]}" and different quotes combinations
At this point I'm a bit confused about how bash quotes and probably indirects may work for this example, none the found answers nor various tries worked so far, aiming to see if there is rather a simple approach to address this or should the way of how arrays are being used here needs to be changed. Any hint is appreciated.
Upvotes: 0
Views: 552
Reputation: 95252
You need to make myarray
a nameref with declare -n
.
declare -n myarray=array_1
Then you reference it as if it were the named array:
$ echo "${myarray[0]}"
Mike
Note that this only works in bash 4.3+, however. Apple is allergic to GPL v3+ so macOS ships with 3.2 in /bin; if you're on a Mac, you'll need to install a newer version (e.g. with MacPorts or Homebrew).
Upvotes: 5
Reputation: 23794
You kind of need, an array of array which does not supported in bash but it does not mean you cannot make it
Here is a dirty way of having an array of array with quick access
#!/bin/bash
# bash strict mode
set -C
set -Ee
set -T
set -u
set -o pipefail
# global array
declare -a arr=();
# get each line as an array, start from 0
function array_of_array(){
# get the index
declare -r index=${1:?'Error: first arg is needed'};
# each line is an array
# delimiter is comma ,
data="name surname 11, name surname 12, 123, 456
name surname 21, name surname 22, 123, 456, 789
name surname 31, name surname 32, 123, 456";
# extract that line, start from 0
mapfile -s $index -t array <<< "$data";
# delimiter is ,
IFS=',';
# remove space after comma
array=${array//, /,}
# save it in arr, a global variable
read -a arr <<< "${array[0]}";
}
# read first line into an array
# read -a arr <<< "$(array_of_array 0)"
array_of_array 0
echo
echo '### first ###'
echo arr: "${arr[0]}"
echo arr: "${arr[1]}"
echo arr: "${arr[2]}"
echo arr: "${arr[3]}"
echo size: "${#arr[@]}"
# read second line into an array
# read -a arr <<< "$(array_of_array 1)"
array_of_array 1
echo
echo '### second ###'
echo arr: "${arr[0]}"
echo arr: "${arr[1]}"
echo arr: "${arr[2]}"
echo arr: "${arr[3]}"
echo arr: "${arr[4]}"
echo size: "${#arr[@]}"
### first ###
arr: name surname 11
arr: name surname 12
arr: 123
arr: 456
size: 4
### second ###
arr: name surname 21
arr: name surname 22
arr: 123
arr: 456
arr: 789
size: 5
Upvotes: 0
Reputation: 29040
If your bash is too old for namerefs you can use indirection:
array=array_1
name1="${!array[0]}"
name2="${!array[1]}"
name3="${!array[2]}"
number1="${!array[3]}"
number2="${!array[4]}"
Demo:
$ array=array_1
$ name1="${!array[0]}"
$ echo "$name1"
Mike
$ array=array_2
$ name1="${!array[0]}"
$ echo "$name1"
Albert
Upvotes: 2
Reputation: 207
@Mike
Proceed as per comment from Mark Reed.
I thought of sharing:
$ cat "73180037.sh"
#!/bin/bash
array_1=("Mike" "George" "Sam" "1234" "5678")
array_2=("Albert" "Isabel" "Sami" "4567" "9821")
array_3=("Michel" "Tom" "Cathy" "321" "5664")
array_4=("name 1" "name 2" "name 3" "1233" "4567")
array_5=...
for i in {1..5}
do
name1=array_$i[0];
name2=array_$i[1];
name3=array_$i[2];
number1=array_$i[3];
number2=array_$i[4];
echo ${!name1} ${!name2} ${!name3} ${!name3} ${!number1} ${!number2}
done
Upvotes: 0