PS3 and SELECT, is it possible to put a line break?

Hi all,

Before I give up on using SELECT for my first attempt at creating a menu driven script, can anyone please advise if it is possible to include a line break for PS3, I've tried putting in a \n and it does not work.

Tried for both bash and ksh and both gives the same result. Preference is to use ksh.

 
menu_main1()
{
   PS3="\n ::  Please choose a VALID option : "
   echo ""
   echo ""
   select choice_main in "Generic SA" "Refresh Tasks" "Others" "Exit"
   do
      case $choice_main in
         "Generic SA" )
            echo "Generic SA"
            clear
            menu_db_admin
            ;;
         "Refresh Tasks" )
            echo "Refresh Tasks"
            ;;
         "Others" )
            echo "Others"
            ;;
         "Exit" )
            exit 0
            ;;
      esac
   done
}

Output is as below:

 

 
1) Generic SA
2) Refresh Tasks
3) Others
4) Exit
\n ::  Please choose a VALID option :

If someone believes there is a better alternative to using select, formatting wise, please advise. An example may be best if any. I've seen heaps of examples in Google but maybe someone has a proven way of making a menu driven script.

Thanks in advance.

The Korn shell allows literal <newline> characters in quoted strings and has a $'...' form to allow the C language's backslash escapes in strings. So either of the following will set PS3 the way you want it:

PS3="
 ::  Please choose a VALID option : "

or

PS3=$'\n ::  Please choose a VALID option : '

The rest of your script looks OK to me (although I don't know what menu_db_admin is supposed to do).

When I'm writing ksh scripts, I usually add the optional opening parentheses in the case clauses to I can more easily match opening and closing braces, parentheses, and square brackets when I'm editing scripts.

Since you have this menu inside a shell function, I would usually get out of the function with a return rather than an exit, but that clearly depends on what you want to do with this function.

#!/bin/ksh
menu_main1() {
        PS3=$'\n ::  Please choose a VALID option : '
        printf "\n\n"
        select choice_main in "Generic SA" "Refresh Tasks" "Others" "Return"
        do
                case $choice_main in
                ( "Generic SA" )
                        echo "Generic SA"
                        clear
                        menu_db_admin;;
                ( "Refresh Tasks" )
                        echo "Refresh Tasks";;
                ( "Others" )
                        echo "Others";;
                ( "Return" )
                        return;;
                esac
        done
}
echo about to call menu_main1
menu_main1
echo menu_main1 has returned
1 Like

Hi Don,

Thanks for your reply. I have to use your first suggestion, why didn't I think of that :wall: Reason being is that your second suggestion does not work on PDKsh and KSH88 :frowning: ...I tried it out on the 3 servers that I need to run the script for and the second suggestion you mentioned only works for KSH93.

Good idea on using the return instead of exit. Just to clarify, the return will always return to the calling sub, correct?

BTW, I also just discovered that if I have more than 4 select options to choose, it wraps into the next column, is there any way to control this behavior?

Thanks again for reply.

Yes, ksh didn't add support for $'...' until ksh93.

I'm not sure what you mean by calling sub . In my example, menu_main was called from the main body of the ksh script. A return from a ksh function or dot script will return to the invoking shell script.

I'm also not sure what you mean by wraps into the next column . If you mean that adding more choices to the select makes that line in your script wider than your screen width or editing window width, you can use a
backslash newline to continue your choices onto the next line. For example:

#!/bin/ksh
menu_main1() {
        PS3="
::  Please choose a VALID option : "
        printf "\n\n"
        select choice_main in "Generic SA" "Refresh Tasks" "Others" \
                "Do Something Else" "Return"
        do
                case $choice_main in
                ( "Generic SA" )
                        echo "Generic SA"
                        clear
                        menu_db_admin;;
                ( "Refresh Tasks" )
                        echo "Refresh Tasks";;
                ( "Others" )
                        echo "Others";;
                ( "Do Something Else" )
                        echo Do Something else;;
                ( "Return" )
                        return;;
                esac
        done
}
echo about to call menu_main1
menu_main1
echo menu_main1 has returned