Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

So I am trying to make a little custom management script for my server, but I am running into a problem for creating my menu script with the right results.

I got the following script

function config
{

list=''

declare -a programs=("docker" "IdontExist" "pushover" "IdontexistEither")

for program in "${programs[@]}"
do
    #Check if command exists on the server
    if hash $program 2>/dev/null; then
        list="${list} "${program}""
    fi
done



title="Config manager"
prompt="Pick an option:"
options=(${list})

echo "$title"
PS3="$prompt "

select opt in "${options[@]}" "Quit"; do
    case "$REPLY" in

    #Dont know how to create this section in a script
    1 ) echo "Update Docker"; break;;
    3 ) echo "Update IdontExist"; break;;
    2 ) echo "Update mytest"; break;;
    4 ) echo "Update IdontExistEither"; break;;

    $(( ${#options[@]}+1 )) ) echo "Goodbye!"; break;;
    *) echo "Invalid option. Try another one.";continue;;
    esac
done

}

My list variable will look as follow

list: "docker" "pushover"

So my options in the script above will not work accordingly. How can I create the options, depending on the list variable?

And I also want to call in certain functions depending on the selected option, for example if somebody choose "docker" I want to call a function named: _docker_config and when its "pushover" I will call a function named _pushover_config How would I also achieve that in the script?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
154 views
Welcome To Ask or Share your Answers For Others

1 Answer

The problem is that you are testing $REPLY instead of $opt:

select opt in "${options[@]}" "Quit"
do

    if [[ -z $opt ]]; then
        echo "Didn't understand "$REPLY" "
        REPLY=
    else
        case "$opt" in

        docker)
            echo "Update Docker"
            break;;
        IdontExist)
            echo "Update IdontExist"
            break;;
        pushover)
            echo "Update mytest"
            break;;
        IdontexistEither)
            echo "Update IdontExistEither"
            break;;
        Quit)
            echo "Goodbye!"
            break;;
        *)
           echo "Invalid option <$opt>. Try another one."
           ;;
        esac
    fi
done

If you use $opt then you don't need to match the menu numbers (which in your case are variable) with the actual entries (program names) - select does that for you. The only time you need $REPLY is when it is invalid (setting REPLY to an empty string redisplays the menu on the next iteration).

Not all of the choices in the case statement will be valid for every run, but that's OK because $opt will only get populated by the valid ones, and the others will not be visible to the user.

You don't need the continue, it does that for you by being in a loop.

Edit:

Here is an alternative using an Associative Array instead of a case statement. It enables the menu and the tests to be dynamic. In the case shown only two of the options have function, that does not have to be the case, it can be any number (with reason).

_docker_config()
{   
    echo "Welcome to docker"
}

_pushover_config()
{   
    echo "Welcome to pushover"
}

# This declares and associative array with the keys being the menu items
# and the values being the functions to be executed.  
# This will have to include all possible programs
declare -A functab=(["Docker"]=_docker_config 
                    ["Pushover"]=_pushover_config)

title="Config manager"
prompt="Pick an option:"

# The options are hard-coded here, of course you will dynamically generate it
# I omitted that for testing purposes
declare -a options=("Docker" "IdontExist" "Pushover" "IdontexistEither")

echo "$title"
PS3="$prompt "

select opt in "${options[@]}" "Quit"
do

    if [[ $opt == "Quit" ]]; then
        echo "Goodbye!"
        break
    fi

    if [[ -z $opt ]]; then
        echo "Didn't understand "$REPLY" " >&2
        REPLY=
    else
        # Here we check that the option is in the associative array
        if [[ -z "${functab[$opt]}" ]]
        then
            echo "Invalid option. Try another one." >&2
        else
            # Here we execute the function
            eval ${functab[$opt]}   # See note below
        fi
    fi
done

The eval is used with caution. Generally this is a command to avoid because it can be a security issue, however we are checking for valid entries so in this case it is justified. Just don't over-use it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...