Create bash select menu with array argument

10,613

My suggestion would be to invert the order of your arguments (though you don't even need the length argument but we'll get to that) and then pass the array as positional parameters to the function.

createmenu ()
{
  arrsize=$1
  echo "Size of array: $arrsize"
  echo "${@:2}"
  select option in "${@:2}"; do
    if [ "$REPLY" -eq "$arrsize" ];
    then
      echo "Exiting..."
      break;
    elif [ 1 -le "$REPLY" ] && [ "$REPLY" -le $((arrsize-1)) ];
    then
      echo "You selected $option which is option $REPLY"
      break;
    else
      echo "Incorrect Input: Select a number 1-$arrsize"
    fi
  done
}

createmenu "${#buckets[@]}" "${buckets[@]}"

Note I also fixed a couple of errors in your function. Namely that you'd missed some spaces between [ and the first argument and that [ isn't an arithmetic context so you need to force one for your math to work).

But back to my comment before about not needing the length argument at all.

If you are using the positional parameters for the array elements then you already have the length... in $# and can just use that.

createmenu ()
{
  echo "Size of array: $#"
  echo "$@"
  select option; do # in "$@" is the default
    if [ "$REPLY" -eq "$#" ];
    then
      echo "Exiting..."
      break;
    elif [ 1 -le "$REPLY" ] && [ "$REPLY" -le $(($#-1)) ];
    then
      echo "You selected $option which is option $REPLY"
      break;
    else
      echo "Incorrect Input: Select a number 1-$#"
    fi
  done
}

createmenu "${buckets[@]}"
Share:
10,613
honestemu3
Author by

honestemu3

Updated on June 04, 2022

Comments

  • honestemu3
    honestemu3 almost 2 years

    I have a function called createmenu. This function will take in an array as the first argument. The second argument will be the size of the array.

    I then want to create a select menu using the elements of that array. This is what I have so far:

    Create the menu with the given array

    createmenu ()
    {
      echo $1
      echo "Size of array: $2"
      select option in $1; do
        if [ $REPLY -eq $2 ];
        then
          echo "Exiting..."
          break;
        elif [1 -le $REPLY ] && [$REPLY -le $2-1 ];
        then
          echo "You selected $option which is option $REPLY"
          break;
        else
          echo "Incorrect Input: Select a number 1-$2"
        fi
      done
    }
    

    This is an example call to the function:

    createmenu ${buckets[*]} ${#buckets[@]}
    

    How do I create this select menu using the elements of the argument array as options?

  • honestemu3
    honestemu3 about 9 years
    Worked like a charm! Might I ask a few clarifying questions? Why do you put quotes around $REPLY? Also, what exactly is ${@:2} doing? Finally, why the double parenthesis around $((arrsize-1))
  • Etan Reisner
    Etan Reisner about 9 years
    In general always quote variable expansions. Is it safer. What if the user input will this break at the prompt? $(( )) is Arithmetic Expansion you need it to get the shell to do math there (otherwise $arrsize-1 just expands to 2-1 or whatever). "${@:2}" is Substring Expansion and that means all the positional parameters starting with the second (as opposed to "$@" which is all the positional parameters).
  • Michael Behrens
    Michael Behrens about 4 years
    In my case, I had to add this after the done line in order to get the value I expected: ` let REPLY=(REPLY-1) # menu started at 1, so we must subtract one`