2017-11-08 32 views
0

私は自分のサーバー用に少しカスタムの管理スクリプトを作ろうとしていますが、正しい結果でメニュースクリプトを作成するための問題が発生しています。bashで選択メニューを作成する

私は私のリスト変数は、したがって、上記のスクリプトでは私のオプションは、それに応じて動作しません

list: "docker" "pushover" 

に従うようになります

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 

} 

次のスクリプトを得ました。リスト変数に応じて、どのようにオプションを作成できますか?

また、「docker」を選択した場合など、選択したオプションに応じて関数を呼び出すこともできます。_docker_configという名前の関数を呼び出したい場合、その「pushover」を_pushover_configという名前の関数私もスクリプトでそれを達成するだろうか?

+1

なぜ 'dialog'プログラムを試してみませんか?人生はずっと楽になります。 – DevilaN

+1

@ cdarke:確かに。私は単に代替案を提案していたので、それはコメントにあった - 答えではない。 – DevilaN

答えて

1

問題は、あなたが$REPLY代わりの$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 

あなたが$optを使用する場合は、あなたが実際のエントリで(あなたのケースで可変である)、メニュー番号と一致する必要はありません。 (プログラム名) - selectあなたのためにそれを行います。 $REPLYが必要な唯一の時間は無効です(空の文字列にREPLYを設定すると、次の反復でメニューが再表示されます)。

caseステートメントのすべての選択肢が有効になるわけではありませんが、これは有効です。$optは有効なものだけが入力され、その他のものはユーザーに表示されないためです。

あなたはcontinueを必要としません。それはあなたがループしているためです。

編集:ここでは

ではなく、case文の連想配列を使用して代替手段です。メニューとテストを動的にすることができます。示されたケースでは、オプションのうちの2つだけが機能を持っていますが、そうである必要はありませんが、それは任意の数(理由あり)です。

_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 

evalのは注意して使用されます。一般に、これはセキュリティの問題である可能性があるため避けるべきコマンドですが、有効なエントリがあるかどうかを確認していますが、この場合は正当なものです。それを過度に使用しないでください。

+0

私はこれを試しましたが、私は行方不明を修正しました。終了時には、何を入れても失敗するでしょう.1を入力すると、「無効なオプション」が表示されます。別のものを試してみてください。 – killstreet

+0

';;'がありません。このコードは私のために働いています。私は、 '$ opt'を表示することによって問題点を示す編集を行っています。キャッチオール '*)'は 'case'ラベルにないエントリをキャッチしなければならないので、スペルや大文字/小文字などを' $ options'のものと照合してください。 – cdarke

+0

これはうまくいきましたが、すでにインストールされているプログラムに応じてオプションが動的に作成されるため、ケースを動的に構築することは可能でしょうか。 – killstreet

関連する問題