私は次のようなbashスクリプトで質問を促しています:
optionsAudits=("Yep" "Nope")
echo "Include audits?"
select opt in "${optionsAudits[@]}"; do
case $REPLY in
1) includeAudits=true; break ;;
2) includeAudits=false; break ;;
"\n") echo "You pressed enter"; break ;; # <--- doesn't work
*) echo "What's that?"; exit;;
esac
done
Enterキーが押されたときにデフォルトのオプションを選択するにはどうすればよいですか? "\n"
ケースはEnterキーをキャッチしません。
補足するために Aserreの役立つ回答 、これはコードの問題を説明し、背景情報と一般的な再利用可能なカスタムselect
を使用して効果的な回避策を提供します空の入力を許可する実装:
明示的に綴るには:select
itself空の入力を無視します(押すだけ Enter)および単に再プロンプトを表示します-ユーザーコードは応答として実行されません。
実際、select
は空の文字列を使用して、invalid選択肢が入力されたことをユーザーコードに通知します。
つまり、出力変数--$opt
、この場合は-がselect
ステートメント内のemptyである場合、無効な選択インデックスを意味します。ユーザーが入力しました。
出力変数は、選択されたオプションのtext-この場合は'Yep'
または'Nope'
のいずれかを受け取ります- ユーザーが入力したindexではありません。
(対照的に、コードは、ユーザーが入力したものを正確に含む出力変数の代わりに$REPLY
を調べます。これには、有効な選択の場合はisindexが含まれます。 、ただし、先頭と末尾に余分な空白が含まれる場合があります)。
あなたがしなかった空の入力を許可したい場合、あなたは単にユーザーに示すことができることに注意してください^C
(Ctrl+C)を使用してプロンプトを中止できます。
select
関数次の関数は、select
の機能を厳密にエミュレートすると同時に、空の入力を許可します(を押すだけです)。 Enter)。この関数は無効な入力をインターセプトし、警告を出力して、次のように再プロンプトすることに注意してください。
# Custom `select` implementation that allows *empty* input.
# Pass the choices as individual arguments.
# Output is the chosen item, or "", if the user just pressed ENTER.
# Example:
# choice=$(selectWithDefault 'one' 'two' 'three')
selectWithDefault() {
local item i=0 numItems=$#
# Print numbered menu items, based on the arguments passed.
for item; do # Short for: for item in "$@"; do
printf '%s\n' "$((++i))) $item"
done >&2 # Print to stderr, as `select` does.
# Prompt the user for the index of the desired item.
while :; do
printf %s "${PS3-#? }" >&2 # Print the Prompt string to stderr, as `select` does.
read -r index
# Make sure that the input is either empty or that a valid index was entered.
[[ -z $index ]] && break # empty input
(( index >= 1 && index <= numItems )) 2>/dev/null || { echo "Invalid selection. Please try again." >&2; continue; }
break
done
# Output the selected item, if any.
[[ -n $index ]] && printf %s "${@: index:1}"
}
あなたはそれを次のように呼ぶことができます:
# Print the Prompt message and call the custom select function.
echo "Include audits (default is 'Nope')?"
optionsAudits=('Yep' 'Nope')
opt=$(selectWithDefault "${optionsAudits[@]}")
# Process the selected item.
case $opt in
'Yep') includeAudits=true; ;;
''|'Nope') includeAudits=false; ;; # $opt is '' if the user just pressed ENTER
esac
注:このコードは問題を解決しませんが、select
ステートメントのより慣用的な使用法を示しています。元のコードとは異なり、このコードは、無効な選択が行われた場合にプロンプトを再表示します。
optionsAudits=("Yep" "Nope")
echo "Include audits (^C to abort)?"
select opt in "${optionsAudits[@]}"; do
# $opt being empty signals invalid input.
[[ -n $opt ]] || { echo "What's that? Please try again." >&2; continue; }
break # a valid choice was made, exit the Prompt.
done
case $opt in # $opt now contains the *text* of the chosen option
'Yep')
includeAudits=true
;;
'Nope') # could be just `*` in this case.
includeAudits=false
;;
esac
注意:
case
ステートメントはselect
ステートメントから移動されました。これは、後者が有効な入力のみを行うことができることを保証するためです。
case
ステートメントは、生のユーザー入力($opt
)ではなく出力変数($REPLY
)をテストし、その変数には選択肢が含まれます。 text、そのindexではありません。
あなたの問題は、select
が空の入力を無視するという事実によるものです。あなたの場合、read
の方が適していますが、select
が自動メニュー作成に提供するユーティリティは失われます。
select
の動作をエミュレートするには、次のようにします。
#!/bin/bash
optionsAudits=("Yep" "Nope")
while : #infinite loop. be sure to break out of it when a valid choice is made
do
i=1
echo "Include Audits?"
#we recreate manually the menu here
for o in "${optionsAudits[@]}"; do
echo "$i) $o"
let i++
done
read reply
#the user can either type the option number or copy the option text
case $reply in
"1"|"${optionsAudits[0]}") includeAudits=true; break;;
"2"|"${optionsAudits[1]}") includeAudits=false; break;;
"") echo "empty"; break;;
*) echo "Invalid choice. Please choose an existing option number.";;
esac
done
echo "choice : \"$reply\""
更新された回答:
echo "Include audits? 1) Yep, 2) Nope"
read ans
case $ans in
Yep|1 ) echo "yes"; includeAudits=true; v=1 ;;
Nope|2 ) echo "no"; includeAudits=false; v=2 ;;
"" ) echo "default - yes"; includeAudits=true; v=1 ;;
* ) echo "Whats that?"; exit ;;
esac
これは、"Yep"
または"1"
または"enter"
のいずれかを受け入れて[はい]を選択し、"Nope"
または"2"
を受け入れていいえを選択し、それ以外のものはすべて破棄します。また、ユーザーが「はい」または「いいえ」を希望したかどうかに応じて、vを1または2に設定します。