2017-07-26 5 views
2

私はそれに複数のメニューを持つbashスクリプトを作ることができますか?複数のユーザープロンプトとプロンプトを戻す機能を組み合わせるにはどうすればよいですか?

例えば、ここでユーザーがそれを実行している時に見るものです:

Type the number of choosing: 
1-play 
2-load 
3-exit 

What is your name: 

::前::

Type the number of choosing: 
1-play 
2-load 
3-exit 

What is your name: 

ブラッド

Where are you from, Brad? 

ペンシルバニア

What is your favourite colour? 
1-blue 
2-red 
3-green 
4-grey 
5-magenta 

、sdfhljalk:J。

What is your favourite colour? 
1-blue 
2-red 
3-green 
4-grey 
5-magenta 

What is your favourite toy? 

電車

What would you like on your sandwich? 

::前::

What is your favourite toy? 

〜!!$#^ & * ()_ + = - {} [] | \ "':;?/>。 <、

What is your favourite toy? 

::終了::

Exiting.... 

私はそれが長いことをお詫び申し上げます、私はちょうど私が作ることにするつもりだ新しいゲームのためのすべての拠点をカバーしたいです。私はこれをすべての質問を終了する質問にしたい。

私はどこにでも::prev::と入力して前の質問に戻りたいと思っています。::exit::はどこでもスクリプトを終了したいと思います。また、番号の付いた質問の間に認識できない入力を残しておき、続行せずに質問を再読み込みするだけでなく、スクリプトを中断させる代わりにスクリプトを中断させるような文字を含む入力(:;[email protected]# ...など)

ご協力いただきありがとうございます。ところで

は、このような状況で行うには、私はOS Xヨセミテを使用してい

+0

あなたは何も試しましたか? – KeithC

+0

私はしばらくしましたが、私のコードが何であるかを覚えていません。私はそれが働いたとは思わない。私はバッチの人です。誰かが私のために全部を書くように要求しているわけではありません。主に ':: prev ::'を使って後方へ行き、偶発的なスクリプトの中断を防ぎ、複数のメニューのようなプロンプトを使うだけでキックスタートが必要です。 – leetbacoon

答えて

2

まず最初は試してみて、一般的に、あなたはこのような何かを実装する方法、を考えることです。おそらく、複雑さの最大の追加は、::prev::を使用して質問を取り返すことでしょう。これは、アプリケーションの状態を何らかの方法で表現する必要があることを意味し、前進または後退できるようになります。

幸いにも、これはかなり簡単です。基本的には、必要なスタックの実装です。いくつかのビジュアル:

                ... 
      <--pop--    <--pop-- Location prompt <--pop-- ... 
        Name prompt   Name prompt    ... 
Main menu --push-> Main menu --push-> Main menu  --push-> ... 

これは、プログラムの個々の部分が自己完結型である必要があることを意味します。関数を使ったシェルスクリプトでこれを簡単に行うことができます。

だから我々はいくつかの部分が必要です。メニューを表示し、ユーザーが値を選択することができます

  • 機能。
  • テキストプロンプトを表示し、ユーザーが値を選択できるようにする機能。
  • プログラムの状態を表すスタックを管理する機能。
  • 各プログラムの個々の機能。

最初にメニュープロンプト機能を書きましょう。この部分はかなり簡単です。 Bashはselectループを使って作業の大部分を行います。これは私たちのためにメニューを表示します。 ::exit::または::prev::などと期待しているようなカスタムロジックを処理できるように、それをラップします。

menu_items=('Item 1' 'Item 2' 'Item 3') 
if ! show_menu 'Please choose an item from the menu below.'; then 
    echo "You entered the command $selection." 
fi 

echo "You chose $selection." 

グレート:私たちは今、そうのように、この機能を使用することができます

function show_menu { 
    echo "$1" # Print the prompt 
    PS3='> ' # Set prompt string 3 to '> ' 
    select selection in "${menu_items[@]}" # Print menu using the menu_items array 
    do 
    if [[ "$REPLY" =~ ^(::exit::|::prev::)$ ]]; then 
     # If the user types ::exit:: or ::prev::, exit the select loop 
     # and return 1 from the function, with $selection containing 
     # the command the user entered. 
     selection="$REPLY" 
     return 1 
    fi 
    # $selection will be blank if the user did not choose a valid menu item. 
    if [ -z "$selection" ]; then 
     # Display error message if $selection is blank 
     echo 'Invalid input. Please choose an option from the menu.' 
    else 
     # Otherwise, return a success return code. 
     return 0 
    fi 
    done 
} 

!今議題の次の項目に、ユーザーからのテキスト入力を受け付けるコードを記述します。

# Prompt for a required text value. 
function prompt_req { 
    # do...while 
    while : ; do 
    # Print the prompt on one line, then '> ' on the next. 
    echo "$1" 
    printf '> ' 
    read -r selection # Read user input into $selection 
    if [ -z "$selection" ]; then 
     # Show error if $selection is empty. 
     echo 'A value is required.' 
     continue 
    elif [[ "$selection" =~ ^(::exit::|::prev::)$ ]]; then 
     # Return non-success return code if ::exit:: or ::prev:: were entered. 
     return 1 
    elif [[ "$selection" =~ [^a-zA-Z0-9\'\ ] ]]; then 
     # Make sure input only contains a whitelist of allowed characters. 
     # If it has other characters, print an error and retry. 
     echo "Invalid characters in input. Allowed characters are a-z, A-Z, 0-9, ', and spaces." 
     continue 
    fi 
    # This break statement only runs if no issues were found with the input. 
    # Exits the while loop and the function returns a success return code. 
    break 
    done 
} 

グレート。この関数は最初の関数と同じように機能します。

if ! prompt_req 'Please enter a value.'; then 
    echo "You entered the command $selection." 
fi 

echo "You entered '$selection'." 

ユーザー入力が処理されたので、スタック管理機能を使用してプログラムフローを処理する必要があります。配列を使用してbashに実装するのは簡単です。

プログラムの一部が実行されて完了すると、フローマネージャーに次の機能の実行を依頼します。フローマネージャは、次の関数の名前をスタックにプッシュするか、配列の末尾に追加して実行します。 ::prev::が入力された場合、最後の関数の名前がスタックからポップされます。または配列の最後の要素が削除され、その前に関数が実行されます。

少ない話、もっとコード:

# Program flow manager 
function run_funcs { 
    # Define our "stack" with its initial value being the function name 
    # passed directly to run_funcs 
    funcs=("$1") 
    # do...while 
    while : ; do 
    # Reset next_func 
    next_func='' 
    # Call the last function name in funcs. 
    if "${funcs[${#funcs[@]}-1]}"; then 
     # If the function returned 0, then no :: command was run by the user. 
     if [ -z "$next_func" ]; then 
     # If the function didn't set the next function to run, exit the program. 
     exit 0 
     else 
     # Otherwise, add the next function to run to the funcs array. (push) 
     funcs+=("$next_func") 
     fi 
    else 
     # If the function returned a value other than 0, a command was run. 
     # The exact command run will be in $selection 
     if [ "$selection" == "::prev::" ]; then 
     if [ ${#funcs[@]} -lt 2 ]; then 
      # If there is only 1 function in funcs, then we can't go back 
      # because there's no other function to call. 
      echo 'There is no previous screen to return to.' 
     else 
      # Remove the last function from funcs. (pop) 
      unset funcs[${#funcs[@]}-1] 
     fi 
     else 
     # If $selection isn't ::prev::, then it's ::exit:: 
     exit 0 
     fi 
    fi 
    # Add a line break between function calls to keep the output clean. 
    echo 
    done 
} 

当社run_funcs機能は想定しています

実行する最初の関数の名前で呼ばれる
  • 、および
  • 各機能が実行されることをプログラムの実行を続行する必要がある場合は、実行する次の関数の名前をnext_funcに出力します。

よし。それは非常に簡単に作業する必要があります。実際にプログラムを書いてみましょう:

function main_menu { 
    menu_items=('Play' 'Load' 'Exit') 
    if ! show_menu 'Please choose from the menu below.'; then 
    return 1 
    fi 

    if [ "$selection" == 'Exit' ]; then 
    exit 0 
    fi 

    if [ "$selection" == 'Load' ]; then 
    # Logic to load game state 
    echo 'Game loaded.' 
    fi 

    next_func='prompt_name' 
} 

function prompt_name { 
    if ! prompt_req 'What is your name?'; then 
    return 1 
    fi 
    name="$selection" 

    next_func='prompt_location' 
} 

function prompt_location { 
    if ! prompt_req "Where are you from, $name?"; then 
    return 1 
    fi 
    location="$selection" 

    next_func='prompt_colour' 
} 

function prompt_colour { 
    menu_items=('Blue' 'Red' 'Green' 'Grey' 'Magenta') 
    if ! show_menu 'What is your favourite colour?'; then 
    return 1 
    fi 
    colour="$selection" 

    next_func='prompt_toy' 
} 

function prompt_toy { 
    if ! prompt_req 'What is your favourite toy?'; then 
    return 1 
    fi 
    toy="$selection" 

    next_func='print_player_info' 
} 

function print_player_info { 
    echo "Your name is $name." 
    echo "You are from $location." 
    echo "Your favourite colour is $colour." 
    echo "Your favourite toy is $toy." 

    # next_func is not set, so the program will exit after running this function. 
} 

echo 'My Bash Game' 
echo 
# Start the program, with main_menu as an entry point. 
run_funcs main_menu 

すべては今すぐです。私たちのプログラムを試してみましょう!

$ ./bash_game.sh 
My Bash Game 

Please choose from the menu below. 
1) Play 
2) Load 
3) Exit 
> ::prev:: 
There is no previous screen to return to. 

Please choose from the menu below. 
1) Play 
2) Load 
3) Exit 
> 2 
Game loaded. 

What is your name? 
> Stephanie 

Where are you from, Stephanie? 
> ::prev:: 

What is your name? 
> Samantha 

Where are you from, Samantha? 
> Dubl*n 
Invalid characters in input. Allowed characters are a-z, A-Z, 0-9, ', and spaces. 
Where are you from, Samantha? 
> Dublin 

What is your favourite colour? 
1) Blue 
2) Red 
3) Green 
4) Grey 
5) Magenta 
> Aquamarine 
Invalid input. Please choose an option from the menu. 
> 8 
Invalid input. Please choose an option from the menu. 
> 1 

What is your favourite toy? 
> Teddie bear 

Your name is Samantha. 
You are from Dublin. 
Your favourite colour is Blue. 
Your favourite toy is Teddie bear. 

これがあります。

+0

あなたは、私がこれまでに会ったことの中で、一番親切で、親切で、最も寛大な人です!私はあなたの助けに十分にあなたに感謝することはできません! – leetbacoon

+2

うれしい私は助けることができました!ちょうどメモ、それは奥さんではなく、卿です。 :) –

+0

私はちょうどもう1つ質問があります、そして、私は設定する必要があります。私は大文字と小文字を区別しない ':: prev ::'と ':: exit ::'を手作業で入力しなくても済むような方法はありますか?たとえば、 ':: eXit ::'や ':: PRev ::'と入力すると、うまく動作します。 – leetbacoon

関連する問題