bash:在“选择"按钮中按回车键时,选择默认值.迅速的 [英] bash: choose default from case when enter is pressed in a "select" prompt

查看:112
本文介绍了bash:在“选择"按钮中按回车键时,选择默认值.迅速的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在这样的bash脚本中提示问题:

I'm prompting questions in a bash script like this:

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"情况没有抓住回车键.

How can I select a default option when enter is pressed? The "\n" case does not catch the enter key.

推荐答案

以补充 Aserre的有用答案,该解释了代码方面的问题,并提供了有效的解决方法,其中提供了背景信息和允许重复输入的通用,可重用的自定义select实现:

To complement Aserre's helpful answer, which explains the problem with your code and offers an effective workaround, with background information and a generic, reusable custom select implementation that allows empty input:

要明确拼写: select 本身忽略空输入(只需按 Enter ),然后只需重新提示-用户代码甚至无法响应运行.

To spell it out explicitly: select itself ignores empty input (just pressing Enter) and simply re-prompts - user code doesn't even get to run in response.

实际上, select使用空字符串向用户代码表示输入了无效选项.
也就是说,如果在select语句中的输出变量$opt(在这种情况下)为 empty ,则表示用户输入了无效的选择索引.

In fact, select uses the empty string to signal to user code that an invalid choice was typed.
That is, if the output variable - $opt, int this case - is empty inside the select statement, the implication is that an invalid choice index was typed by the user.

输出变量接收所选选项的 text -在这种情况下为'Yep''Nope'-不是 index 由用户键入.

The output variable receives the chosen option's text - either 'Yep' or 'Nope' in this case - not the index typed by the user.

(相反,您的代码将检查$REPLY而不是输出变量,该输出变量完全包含用户键入的内容,如果有效,该变量为 index 选择,但可能包含多余的前导和尾随空白).

(By contrast, your code examines $REPLY instead of the output variable, which contains exactly what the user typed, which is the index in case of a valid choice, but may contain extra leading and trailing whitespace).

请注意,如果您不想想要允许空输入,则可以 只需在提示文本中向用户指示 ^C( Ctrl + C )可用于中止提示.

Note that in the event that you didn't want to allow empty input, you could simply indicate to the user in the prompt text that ^C (Ctrl+C) can be used to abort the prompt.

以下功能紧密模拟select的功能,同时还允许空输入(只需按 Enter ).请注意,该函数将拦截无效输入,打印警告并重新提示:

The following function closely emulates what select does while also allowing empty input (just pressing Enter). Note that the function intercepts invalid input, prints a warning, and re-prompts:

# 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语句的更多惯用用法;与原始代码不同,此代码会在选择无效的情况下重新显示提示:


Optional reading: A more idiomatic version of your original code

Note: This code doesn't solve the problem, but shows more idiomatic use of the select statement; unlike the original code, this code re-displays the prompt if an invalid choice was made:

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语句移出,因为后者现在保证只能进行有效输入.

  • The case statement was moved out of the select statement, because the latter now guarantees that only valid inputs can be made.

case语句测试输出变量($opt)而不是原始用户输入($REPLY),并且该变量包含选项 text ,而不是其 index .

The case statement tests the output variable ($opt) rather than the raw user input ($REPLY), and that variable contains the choice text, not its index.

这篇关于bash:在“选择"按钮中按回车键时,选择默认值.迅速的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆