1

I have this current function used to create an array in a menu style (associative arrays can't be used in the scenario).

declare -a array1=("host1" "host2" "host3")
declare -a array2=("ip1" "ip2" "ip3")

function menusetup {

  iter=0
  for ((i=0; i<(count*2); i+=2)); do
    menu[$i]=${array1[$iter]}
    menu[$i+1]=${array2[$iter]}
    ((iter++))
  done
}

menusetup

which gives me the menu array with {"host1" "ip1" "host2" "ip2" "host3" "ip3" This is working perfect for what I needed, but now I want to reuse this function to pass any 2 arrays, something like this.

function menusetup {

  iter=0
  for ((i=0; i<(count*2); i+=2)); do
    menu[$i]=${$1[$iter]}
    menu[$i+1]=${$2[$iter]}
    ((iter++))
  done
}

menusetup "${array3[@]}" "${array4[@]}"

Edit: I know the second example passes the entire list of elements of the array. I want to know if there is a way to pass and substitute the array

  • What is `count`? It's not defined in your code. Btw you're probably looking for namerefs – oguz ismail Oct 21 '19 at 16:27
  • 1
    ksh-ish `function func {}` is correct and will work on bash, it is not specified by posix. So it's better to stick to POSIX `func() {}` that will work anywhere, see [bash Obsolete and deprecated syntax](https://wiki-dev.bash-hackers.org/scripting/obsolete). `${$1[$iter]}` I think this is your problem, right? If so use bash nameref, but the syntax for arrays is strange. – KamilCuk Oct 21 '19 at 16:29
  • Please provide an [mcve] . – Nic3500 Oct 21 '19 at 16:29
  • 1
    `menu setup "${array3[@]}"` doesn't pass an array as an argument; it passes all the *elements* of an array, each as a separate argument. Arrays are not first-class values in `bash`. – chepner Oct 21 '19 at 16:32
  • 2
    You are passing a single list comprising the elements from both arrays, but there is no way to know where the first ends and the second begins. If they are both the same length, obviously the second begins halfway. – tripleee Oct 21 '19 at 16:32
  • 1
    @oguzismail, sorry didn't think it was needed to address the problem. Count is the length on one of the arrays (both are always the same length) – Daniel Schreiber Oct 21 '19 at 16:43
  • @KamilCuk yes that part is the question. I'm not too familiar with nameref, sorry. How would I use it in my example? – Daniel Schreiber Oct 21 '19 at 16:46
  • @triplee, sorry should've said form the start I know that's what happening XD I wanted to just illustrate what I was hoping to achieve. Is there any way to pass the array like that? – Daniel Schreiber Oct 21 '19 at 16:48

1 Answers1

0

While you can use bash namereferences:

array3=(1 2 3)
array4=(a b c)
menusetup() {
   declare -g menu
   declare -n count1=$1[@]
   count=$(( ${#count1} ))
   iter=0
   for ((i=0; i<count; i+=2)); do
       declare -n el1=$1[$iter]
       declare -n el2=$2[$iter]
       menu[$i]=$el1
       menu[$i+1]=$el2
       ((iter++))
    done
}

menusetup array3 array4
declare -p menu
# will output:
# declare -a menu=([0]="1" [1]="a" [2]="2" [3]="b" [4]="3" [5]="c")

And this is valid and useful programming style, It's way better and easier to think of bash as pipelines. You don't need state, you don't need to "iterate" over arrays.

Think of bash as streams. What you are doing here is you are "zip"-ing two arrays. So first print each array element on newline separated items, then use paste to join two newline separated streams together, specify the paste separator to newline. Then read it to an array, either with readarray < <(...) or IFS=$'\n' menu=( $(...) ).

Assuming there are no newline characters in array values, the whole work your function is doing can be simply done with:

readarray -t menu < <(paste -d$'\n' <(printf "%s\n" "${array3[@]}") <(printf "%s\n" "${array4[@]}") )
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Dude, Honestly thank you SO much! This is exactly what I was looking for. I'm a novice java coder, so not too familiar with all of bash's syntax and capabilities. That one liner really surprised me, but will be sticking to the function for now while I get more comfortable with bash – Daniel Schreiber Oct 21 '19 at 17:51