Filip
Filip

Reputation: 1491

Access range of indirectly referenced array in bash

I have a bash script that needs to build some sets each containing 1 element from multiple queues (i'm considering using arrays to store these) For example if i have the following queues:

array1=(a b c e f)                                                            
array2=(x y z)                                                                
array3=(1 2 3 4)

I need to obtain the following arrays (not necessarily all at once, i process the resulting arrays one at a time)

a x 1
b y 2
c z 3
e 4
f

The number of arrays is dynamic.

So basically i need to pop the first element from each array and put in another array. I know i can pop the first element from an array like this:

 el1=${array1[0]}
 array1=(${array1[@]:1:$((${#array1[@]}))})

Also, i know i can extract a value from an indirectly referenced array like this:

val=$(eval echo \${$arr[0]})

My question is: How can i rewrite the part that pops the first element from an array to use indirect references.

Here is the full test script:

#!/bin/bash

set -e 
set -u


array1=(a b c e f)
array2=(x y z)
array3=(1 2 3 4)

finished=false
while ! $finished; do
   finished=true

   array4=()
   for arr in array1 array2 array3; do
      val=$(eval echo \${$arr[0]})
      if [ ! -z $val ]; then
         array4=(${array4[@]} $val)
         $arr=(\${$arr[@]:1:$((\${#$arr[@]}))})
      fi
   done

   l4=${#array4[@]}
   if [ $l4 -gt 0 ]; then
      finished=false

      for i in ${array4[@]}; do
         echo $i
      done
   fi

done

Upvotes: 0

Views: 343

Answers (1)

Fritz G. Mehner
Fritz G. Mehner

Reputation: 17198

array1=(a b c e f )                                                            
array2=(x y z)                                                                
array3=(1 2 3 4)

cnt=0
while : ; do
  line=''
  for a in ${!array*}; do               # loop over names "array*"
    val=$(eval echo \${$a[$cnt]} )
    line="$line ${val:- }"              # build line
  done
  ((cnt++))
  [[ $line =~ ^\ +$ ]] && break         # break if line has only blanks
  echo -e "${line:1}"
done

Output:

a x 1
b y 2
c z 3
e   4
f      

Upvotes: 1

Related Questions