题 如何在Linux shell脚本中提示是/否/取消输入?


我想在shell脚本中暂停输入,并提示用户进行选择。标准的“是,否或取消”类型问题。如何在典型的bash提示符中完成此操作?


1101
2017-10-22 17:03


起源




答案:


在shell提示符下获取用户输入的最简单且最广泛可用的方法是 read 命令。说明其用法的最佳方式是一个简单的演示:

while true; do
    read -p "Do you wish to install this program?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

Steven Huwig指出的另一种方法是Bash select 命令。这是使用相同的示例 select

echo "Do you wish to install this program?"
select yn in "Yes" "No"; do
    case $yn in
        Yes ) make install; break;;
        No ) exit;;
    esac
done

select 您不需要清理输入 - 它会显示可用的选项,并键入与您选择的数字相对应的数字。它也会自动循环,所以不需要 while true 如果它们给出无效输入,则循环重试。

另外,请查看 优秀的答案 作者:F. Hauri。


1272
2017-10-22 17:08



读-p“你想安装这个程序吗?”你... - Steve Baker
在OS X Leopard中使用Bash,我改变了 exit 至 break 当我选择“否”时,不要关闭标签。 - Trey Piepmeier
@Trey,你可能想用 return 代替 exit 在这种情况下。 - glenn jackman
我只想感谢那些尝试修复语法错误的人,即使您的编辑被拒绝了。对不起,他们拒绝了;你是对的。谢谢你的修复。 - Myrddin Emrys
FWIW,我用这个例子来创建一个我打算通过远程SSH会话触发的脚本。我的SSH命令看起来像这样: ssh my-server 'path/to/myscript.sh'。执行这种方式时,提示文本为 read -p 命令没有显示。但是,输出来自 echo 命令呢。所以对我来说,更好的解决方案是使用 echo -n "Do something? " 其次是 read yn。 - Travesty3


一个通用问题至少有五个答案。

取决于

  •  合规:可以在通用的穷人系统上工作  环境
  •  具体:使用所谓的 bash化

如果你想要的话

  • 简单的``在线''问题/答案(通用解决方案)
  • 非常格式化的界面,比如  或更多图形使用libgtk或libqt ...
  • 使用强大的readline历史记录功能

1. POSIX通用解决方案

你可以使用 read 命令,然后是 if ... then ... else

echo -n "Is this a good question (y/n)? "
read answer

# if echo "$answer" | grep -iq "^y" ;then


375
2018-01-10 10:53



注意 stty 提供 -g 使用选项: old_stty=$(stty -g); stty raw -echo; …; stty "$old_stty"。这将完全恢复设置,这可能与也可能不同 stty -sane。 - Jonathan Leffler
read answer将在空格和换行符之前解释反斜杠,否则将删除它们很少用于它们。使用 read -r answer 而是按照 SC2162。 - vlfig
@vlfig A同意:期待用户输入的反斜杠 是/否/取消 对话框是 很少打算......我认为这是主要原因,因为我没有使用过 -r 选项。 - F. Hauri
对于OP的问题,“使用readline的历史”方法是非常不合适的。无论如何,我很高兴你把它包括在内。我有几十个更复杂的脚本,我打算用这种模式更新! - Bruno Bronosky
您可以使用 case 对于POSIX以及bash(使用通配符条件而不是bash子字符串: case $answer in; [Yy]* ) echo Yes ;;),但我更喜欢使用条件语句,而不是喜欢 [ "$answer" != "${answer#[Yy]}" ] 超过你的 echo "$answer" | grep -iq ^y。它更便携(一些非GNU greps没有实现 -q 正确),它没有系统调用。 ${answer#[Yy]} 使用参数扩展来删除 Y 要么 y 从一开始 $answer,当存在任何一个时,造成不平等。这适用于任何POSIX shell(dash,ksh,bash,zsh,busybox等)。 - Adam Katz


echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"

333
2017-10-22 17:08



我不同意,因为它只实现了DOS中“是,否,取消”对话框的一部分功能。它无法实现的部分是输入检查...循环,直到收到有效的答案。 - Myrddin Emrys
(最初的问题标题是“如何在Linux shell脚本中提示输入?”) - Pistos
但是原始问题描述没有改变,并且总是要求对是/否/取消提示做出响应。标题已经更新,比我原来的标题更清晰,但问题描述总是很清楚(在我看来)。 - Myrddin Emrys


你可以使用内置的  命令;使用 -p 用于提示用户提问的选项。

从BASH4开始,您现在可以使用 -i 建议一个答案,所以用户只需要按 return 输入它:

read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH

(但请记住使用“readline”选项 -e 允许使用箭头键进行行编辑)

如果你想要一个“是/否”逻辑,你可以这样做:

read -e -p "
List the content of your home dir ? [Y/n] " YN

[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/

117
2018-05-13 04:44



应当指出的是 FILEPATH 是您选择的变量名称,并使用命令提示符的答案进行设置。所以,如果你那么跑 vlc "$FILEPATH", 例如, vlc 会打开那个文件。 - Ken Sharp


巴什有 选择 以此目的。

select result in Yes No Cancel
do
    echo $result
done

95
2017-10-22 18:14



+1 Geniously简单的解决方案。唯一的事情:这将提示并提示并提示......直到你添加一个 exit 里面:) - kaiser
(kaiser:要打破它,只需输入EOT: Ctrl-D。但是,当然,使用它的真实代码需要在身体中断或退出。) - Zorawar
但是,这不允许您输入y或n。您可以通过输入1 2或3进行选择。 - djjeck
exit 将一起退出脚本, break 只会退出你所在的循环(如果你在 while 要么 case 循环) - wranvaud


read -p "Are you alright? (y/n) " RESP
if [ "$RESP" = "y" ]; then
  echo "Glad to hear it"
else
  echo "You need more bash programming"
fi

51
2018-02-03 13:23





这是我放在一起的东西:

#!/bin/sh

promptyn () {
    while true; do
        read -p "$1 " yn
        case $yn in
            [Yy]* ) return 0;;
            [Nn]* ) return 1;;
            * ) echo "Please answer yes or no.";;
        esac
    done
}

if promptyn "is the sky blue?"; then
    echo "yes"
else
    echo "no"
fi

我是一个初学者,所以带上一粒盐,但似乎有效。


27
2017-08-30 17:59



如果你改变了 case $yn in 至 case ${yn:-$2} in 那么你可以使用第二个参数作为默认值Y或N. - jchook