3

I need to create a select menu with six options using the select loop and the case instruction BUT NOT THE ECHO COMMAND FOR THE MENU OPTION and they have to display like this:

1) opt1
2) opt2
3) opt3
4) opt4
5) opt5
6) opt6

And not like:

1) opt1 3) opt3 5) opt5
2) opt2 4) opt4 6) opt6

So far I have this code, but the problem is with the display, with 5 options it displays vertically, but with 6 it displays side by side:

#! /bin/sh
PS3="Enter your choice :"
select choice in "opt1" "opt2" "opt3" "opt4" "opt5" "Exit"; do
case $REPLY in
    1) echo "$choice";;
    2) echo "$choice";;
    3) echo "$choice";;
    4) echo "$choice";;
    5) echo "$choice";;
    6) echo "see you next time";break;;
    *) echo "Wrong choice!";;
esac
done
4
  • 1
    You may find a number of solutions over here: askubuntu.com/questions/1705/… Commented May 25, 2013 at 14:12
  • 1
    on the ubuntu 12.04 system I'm on, /bin/sh is a symlink to dash which does not even have the select command. using bash, the select menu shows up in one column. what shell/distro are you using? Commented May 25, 2013 at 16:17
  • I'm on Linux CentOS 6.3 and I'm using the Terminal bash Commented May 25, 2013 at 17:31
  • bash and ksh have select, but yes, the output is in one column like in my example below even with 6 options on my box as well. What version of bash do you have? Commented May 25, 2013 at 18:46

4 Answers 4

5

Adjusting the COLUMNS variable helps to limit the number of columns in the menu. I typically do (in a script):

COLUMNS=1
select ...

when I want one column all the time.

To be precise, COLUMNS=1 means that your TERMINAL is ONE CHARACTER wide. The select command then has no choice but to then print ONE COLUMN of menu items.

To be REALLY accurate, you could

  1. find the length of the longest item (itemLen)

THIS IS INCORRECT=> 2. find the number of items and mod by ten to get the max number of digits (numberLen) <=

  1. find the total number of items "n" and calculate int(log10(n))+1 (numberLen)
  2. COLUMNS=((itemLen + numberLen = 2))

where the '2' is for the paren and space between the menu item number and the item. But this is not necessary.

Sign up to request clarification or add additional context in comments.

Comments

3

Try something like this:

menu()
{
    cat <<EOF
  1) opt1
  2) opt2
  3) opt3
  4) opt4
  5) opt5
  6) opt6
  q) quit
EOF

    echo -n "make your choice > <^H^H"
    read -n 1 foo
    echo

    case "$foo" in
        1|opt1) echo "opt1" ;;
        2|opt2) echo "opt2" ;;
        3|opt3) echo "opt3" ;;
        4|opt4) echo "opt4" ;;
        5|opt5) echo "opt5" ;;
        6|opt6) echo "opt6" ;;
        q|quit) echo "bye bye!" ;;
    esac
}

The ^Hs stand for the ASCII sequence 0x08 or BS (backspace).

(In vim you can type this with CTRL+v and then CTRL+h)

Comments

2

I've got the same problem. I didn't understand how exactly select uses LINES and COLUMNS (see "Shell Variables" in the bash man page), but setting COLUMNS to 1 (some small value indeed) helped me.

1 Comment

The best explanation I have ever come across is by Mark G. Sobell in his book, here: books.google.com/…
1

You can use the select builtin, if available:

#!/bin/bash

select o in opt{1..6}; do
    case "${o}" in
        opt[1-6])
            break
            ;;
        *)
            echo "Invalid choice '${REPLY}', please pick one of the above"
            ;;
    esac
done
echo "You picked: ${o}"

Example run:

$ ./t.sh
1) opt1
2) opt2
3) opt3
4) opt4
5) opt5
6) opt6
#? 9
Invalid choice '9', please pick one of the above
#? asdf
Invalid choice 'asdf', please pick one of the above
#? 1
You picked: opt1

Comments

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.