2011-01-18 12 views
2

私はスクリプトの間の選択肢(サブメニューの一種)の他のリストの間の選択につながるケース文でスクリプトを実行したい:bashスクリプト、case文とサブメニュー

#!/bin/bash 

echo "Your choice ?" 
echo "1) Foo" 
echo "2) Bar" 
echo "3) Stuff" 
read case; 

case $case in 

#and this is where I would like to allow 
#(here a simplified example I do not manage to code) 

1) What script ? # may I use another case statement ? 
    a) Foo1;; 
    b) Foo2;; 
2) What script ? # d° 
    a) Bar1;; 
    b) Bar2;; 
    c) Bar3;; 

esac 

FOO1、foo2は、Bar1、Bar2、Bar3は実際にはbashスクリプトであり、スクリプト内からsh foo1などを呼び出したいと思います。

どのように進める必要がありますか: case文をcase文に含めることができますか(選択肢が多数ある場合はif文よりも優れています)。 他のスクリプト内からスクリプトを呼び出すにはどうすればよいですか?あなたの助けを事前に

おかげ

THG

+0

スクリプト内からスクリプトを呼び出すには、コマンドラインの場合と同じように、他のスクリプトの名前を呼び出すだけです。 – chrisaycock

答えて

4

Dennis' answer:それは次のようになります。スクリプトを読みやすくするために、ちょうど、機能でそれを行う方法を説明します

  • which_foo内部case$REPLYの使用である:さておき、注意点としては

    function which_foo { 
        local foo_options=("foo1" "foo2" "cancel") 
        local PS3="Select foo: " 
    
        select foo in "${foo_options[@]}" 
        do 
         case $REPLY in 
          1) ./foo1.sh 
           break ;; 
    
          2) ./foo2.sh 
           break ;; 
    
          3) break ;; 
         esac 
        done 
    } 
    
    ACTIONS=("foo" "bar" "quit") 
    PS3="Select action: " 
    
    select action in "${ACTIONS[@]}" 
    do 
        case $action in 
         "foo") which_foo 
           break ;; 
    
         "bar") which_bar # Not present in this example 
           break ;; 
    
         "quit") break ;; 
        esac 
    done 
    

    をオプションのテキストではなく、ユーザーが選択した番号に自動的に設定されます。

  • 各オプションでbreakの使用。それらがなければ、selectはあなたをループに入れます。そのため、ユーザーはもう一度選択肢を入力するよう求められます。
  • selectは決してPS3の値を変更しないので、メニューの各レベルを切り替えるときは自分で行う必要があります。
+0

おかげさまで(デニスの私の "答え"参照)...と同じ答え – ThG

+0

+1バリエーションを表示し、詳細を与えるために。関数内で 'local PS3'を使うことができますので、" global "の値を保存して復元する必要はありません。関数の中に 'FOO_OPTIONS'を入れて' local'にすることもできます。 'select'変数(あなたの例では' $ action')の代わりに '$ REPLY'を使うと動作しますが、コードはあまり読みにくいです。 'break'を使うと、いくつかの用途のために外側に' while'を置いておきたいかもしれません。 –

+0

「ローカルPS3」について私は知らなかった。私はそれに応じて私の例を更新しました。デニスのおかげで、ありがとう。 – Rodrigue

4

はい、あなたはネストできcase文を。また、echoreadステートメントのすべてではなく、selectステートメントの使用を検討する必要があります。

options=("Option 1" "Option 2" "Option3" "Quit") 
optionsprompt='Please enter your choice: ' 

sub1=("Option 1 sub 1" "Option 1 sub 2") 
sub1prompt='Please enter your choice: ' 

PS3=$optionsprompt 
select opt in "${options[@]}" 
do 
    case $opt in 
     "Option 1") 
      echo "you chose choice 1" 
      PS3=$sub1prompt 
      select sub1opt in "${sub1[@]}" 
      do 
       case $sub1opt in 
        "Option 1 sub 1") 
         echo "you chose choice 2" 
         ;; 
        "Option 1 sub 2") 
         echo "you chose choice 2" 
         ;; 
       esac 
      done 
      ;; 
     "Option 2") 
      echo "you chose choice 2" 
      ;; 
     "Option 2") 
      echo "you chose choice 3" 
      ;; 
     "Quit") 
      break 
      ;; 
     *) echo invalid option;; 
    esac 
done 

最初のレベルのメニューは次のようになります。

1) Option 1 
2) Option 2 
3) Option3 
4) Quit 
Please enter your choice: 

しかし、それは非常に迅速に非常に毛深い得ることができます。内部のselect/caseステートメントが別々の関数にあるか、抽象化されているので、それらを制御する引数を渡すことができる関数に分割する方が良いでしょう。

別のスクリプトを呼び出すには、そのディレクトリを保持する変数を設定するとよいでしょう。あなたが欲しいものを行う必要があります

basedir=/some/path 

case ... 
... 
    $basedir/Foo # call the script 
+0

あなたの非常に迅速な答えに感謝します。私はまだそれを "把握"していない。私はそれを考える必要があります(学習者であることを前提に、いくつかの宿題をする必要があります...)。 – ThG

+0

と@Rodrigue:思ったことを数回してしまった(例えば、私はスクリプトのためにXをchmodに忘れてしまった...)。ありがとう、感謝している。どちらも最終的にそれを作った。もう一度ありがとう – ThG