まず最初は試してみて、一般的に、あなたはこのような何かを実装する方法、を考えることです。おそらく、複雑さの最大の追加は、::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.
これがあります。
あなたは何も試しましたか? – KeithC
私はしばらくしましたが、私のコードが何であるかを覚えていません。私はそれが働いたとは思わない。私はバッチの人です。誰かが私のために全部を書くように要求しているわけではありません。主に ':: prev ::'を使って後方へ行き、偶発的なスクリプトの中断を防ぎ、複数のメニューのようなプロンプトを使うだけでキックスタートが必要です。 – leetbacoon