LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   bash script: using "select" to show multi-word options? (like "option 1"/"o (http://www.linuxquestions.org/questions/programming-9/bash-script-using-select-to-show-multi-word-options-like-option-1-o-317671/)

zidane_tribal 04-27-2005 07:35 AM

bash script: using "select" to show multi-word options? (like "option 1"/"o
 
heya

hit a bit of a problem. im currently attempting to learn bash scripting, with the aim of making a little menu script for a freind. i want to use "select" within my script, but i cant seem to figure out how to get it to list many-word options.

an example might be in order.

if i use this script:

Code:

#!/bin/bash
options1="option1 option2 quit"

echo options1 $options1

select opt in $options1 ; do
echo $opt
if [ "$opt"="quit" ]; then
        exit
fi
done

i get this output:

Code:

1) option1
2) option2
3) quit
#? 3

which is nice.... but, what i really want, is to get something like this output (i just typed this out, i cant make select output this)

Code:

1) option 1
2) option 2
3) quit
#? 3

(note the space between "option" and "number")
when i tried to make something like that, using this script:

Code:

#!/bin/bash
options1="\"option 1\" \"option 2\" \"quit\""

echo options1 $options1

select opt in $options1 ; do
echo $opt
if [ "$opt"="quit" ]; then
        exit
fi
done

i get output like this:

Code:

1) "option
2) 1"
3) "option
4) 2"
5) "quit"
#? 5

now, i know that i can have multiword options if i specify them in the select line (like: select opt in "option 1" "option 2" "quit"), but i would like to specify them as a variable. it just seems neater that way.

so, the question becomes, how do i make select see the multiple word options held in my variable?

many thanks in advance to any guidance you can give.

jlliagre 04-27-2005 08:18 AM

Try that one:

Code:

#!/bin/bash
options1="\"option 1\" \"option 2\" \"quit\""

echo options1 $options1

eval set $options1
select opt in "$@"
do
echo $opt
if [ "$opt"="quit" ]; then
        exit
fi
done


zidane_tribal 04-27-2005 08:27 AM

w00t

works a treat :)

thanks jlliagre, much appreciated :)

gloriant 07-24-2007 11:03 AM

you could also use the bash-capability for arrays:
Code:

#!/bin/bash

#define options as array
declare -a options

#set first empty position with new value
options[${#options[*]}]="option 1";
options[${#options[*]}]="option 2";
options[${#options[*]}]="quit";

#expand to quoted elements:
select opt in "${options[@]}"; do
  case ${opt} in
  ${options[0]}) echo "Polly wants a cookie"; ;;
  (quit) break; ;;
  (*) echo "${opt}"; ;;
  esac;
done


8#4247 10-25-2011 02:20 PM

The following would also do...... :)
 
Code:

#!/bin/bash
options="option 1,option 2,quit"
OIFS=$IFS  # Save the current IFS (Internal Field Separator)
IFS=','    # New IFS
select opt in $options
do
echo $opt
if [[ "$opt" == "quit" ]]
then
IFS=$OIFS  # Restore the IFS
exit
fi
done


David the H. 10-26-2011 01:52 PM

You should take care when resurrecting old threads. It should generally only be done when you have something significant to add to them. And make sure you clearly point out that you are doing so, otherwise people tend to overlook the dates and start replying to a long-dead conversation.

That said, you did post something significant. :) But I'd still say arrays are the way to go. Resetting the IFS works, but to my mind is best used to convert strings into arrays for further use.

(Arrays are painfully underutilized in bash scripting, IMO. Any time you have a list of strings to work on, filenames, options, etc., put it into an array first.)

And now to add my own observation...this part of gloriant's post above can be made much cleaner:
Code:

#set first empty position with new value
options[${#options[*]}]="option 1";
options[${#options[*]}]="option 2";
options[${#options[*]}]="quit";

This is an awkward way to add elements to an array. You can use this instead:

Code:

options+=( "option 1" "option 2" "quit" )
array+=() tells it to append the elements to an existing array, while array=() will reset it with the new values. Either one could be used here, since you're starting with an empty array anyway.

Combine this with IFS to split a string stored in a variable:
Code:

optionstring="option 1,option 2,quit"

IFS=","
options=( $optionstring )
IFS=$' \t\n'

Notice that this is one of the rare instances where you do not want to quote the variable. The last line also demonstrates how you can manually reset IFS to the default value ($'' is ansi-c style quoting. See the QUOTING section of the bash man page).

It's also possible to simply unset IFS, and the shell will behave as if it were set to the default.

maine_guy 03-21-2013 10:35 AM

Replying to ancient threads
 
I see nothing wrong with replying to ancient threads. Perhaps the OP is no longer around but people searching for answers will certainly find these old relics and a new reply could help them.


All times are GMT -5. The time now is 11:55 PM.