2

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?

1 Answer 1

6

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[@]}"
Sign up to request clarification or add additional context in comments.

3 Comments

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))
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).
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`

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.