#!/bin/bash
function ask_user() {
echo -e "
#~~~~~~~~~~~~#
| 1.) Yes |
| 2.) No |
| 3.) Quit |
#~~~~~~~~~~~~#\n"
read -e -p "Select 1: " choice
if [ "$choice" == "1" ]; then
do_something
elif [ "$choice" == "2" ]; then
do_something_else
elif [ "$choice" == "3" ]; then
clear && exit 0
else
echo "Please select 1, 2, or 3." && sleep 3
clear && ask_user
fi
}
ask_user
发布此方法是希望有人可能觉得它有用且节省时间 .
9
这是我放在一起的东西:
#!/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
我是一个初学者,所以带上一粒盐,但似乎有效 .
4
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
3
使用最少行数实现此目的的最简单方法如下:
read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;
if [ "$CONDITION" == "y" ]; then
# do something here!
fi
select result in Yes No Cancel
do
echo $result
done
0
受到@Mark和@Myrddin的答案的启发,我创建了这个函数用于通用提示
uniprompt(){
while true; do
echo -e "$1\c"
read opt
array=($2)
case "${array[@]}" in *"$opt"*) eval "$3=$opt";return 0;; esac
echo -e "$opt is not a correct value\n"
done
}
像这样用它:
unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
138
使用 read 命令:
echo Would you like to install? "(Y or N)"
read x
# now check if $x is "y"
if [ "$x" = "y" ]; then
# do something here!
fi
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
do_xxxx=y # In batch mode => Default is Yes
[[ -t 0 ]] && # If TTY => Prompt the question
read -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx # Store the answer in $do_xxxx
if [[ $do_xxxx =~ ^(y|Y|)$ ]] # Do if 'y' or 'Y' or empty
then
xxxx
fi
echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
if echo "$answer" | grep -iq "^y" ;then
echo Yes
else
echo No
fi
#/bin/sh
echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo
answer=$( while ! head -c 1 | grep -i '[ny]' ;do true ;done )
stty $old_stty_cfg
if echo "$answer" | grep -iq "^y" ;then
echo Yes
else
echo No
fi
if whiptail --yesno "Is this a good question" 20 60 ;then
echo Yes
else
echo No
fi
根据您的系统,您可能需要将 whiptail 替换为另一个类似的工具:
dialog --yesno "Is this a good question" 20 60 && echo Yes
gdialog --yesno "Is this a good question" 20 60 && echo Yes
kdialog --yesno "Is this a good question" 20 60 && echo Yes
其中 20 是对话框的行数高度, 60 是对话框的宽度 . 这些工具都具有几乎相同的语法 .
DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...
2. Bash特定解决方案
基本在线方法
read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
y|Y )
echo Yes
;;
* )
echo No
;;
esac
我更喜欢使用 case 所以我甚至可以测试 yes | ja | si | oui 如果需要的话......
符合单键功能
在bash下,我们可以为 read 命令指定预期输入的长度:
read -n 1 -p "Is this a good question (y/n)? " answer
在bash下, read 命令接受超时参数,这可能很有用 .
read -t 3 -n 1 -p "Is this a good question (y/n)? " answer
[ -z "$answer" ] && answer="Yes" # if 'yes' have to be default choice
专用工具的一些技巧
更复杂的对话框,超出简单的 yes - no 目的:
dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe
进度条:
dialog --gauge "Filling the tank" 20 60 0 < <(
for i in {1..100};do
printf "XXX\n%d\n%(%a %b %T)T progress: %d\nXXX\n" $i -1 $i
sleep .033
done
)
小演示:
#!/bin/sh
while true ;do
[ -x "$(which ${DIALOG%% *})" ] || DIALOG=dialog
DIALOG=$($DIALOG --menu "Which tool for next run?" 20 60 12 2>&1 \
whiptail "dialog boxes from shell scripts" >/dev/tty \
dialog "dialog boxes from shell with ncurses" \
gdialog "dialog boxes from shell with Gtk" \
kdialog "dialog boxes from shell with Kde" ) || exit
clear;echo "Choosed: $DIALOG."
for i in `seq 1 100`;do
date +"`printf "XXX\n%d\n%%a %%b %%T progress: %d\nXXX\n" $i $i`"
sleep .0125
done | $DIALOG --gauge "Filling the tank" 20 60 0
$DIALOG --infobox "This is a simple info box\n\nNo action required" 20 60
sleep 3
if $DIALOG --yesno "Do you like this demo?" 20 60 ;then
AnsYesNo=Yes; else AnsYesNo=No; fi
AnsInput=$($DIALOG --inputbox "A text:" 20 60 "Text here..." 2>&1 >/dev/tty)
AnsPass=$($DIALOG --passwordbox "A secret:" 20 60 "First..." 2>&1 >/dev/tty)
$DIALOG --textbox /etc/motd 20 60
AnsCkLst=$($DIALOG --checklist "Check some..." 20 60 12 \
Correct "This demo is useful" off \
Fun "This demo is nice" off \
Strong "This demo is complex" on 2>&1 >/dev/tty)
AnsRadio=$($DIALOG --radiolist "I will:" 20 60 12 \
" -1" "Downgrade this answer" off \
" 0" "Not do anything" on \
" +1" "Upgrade this anser" off 2>&1 >/dev/tty)
out="Your answers:\nLike: $AnsYesNo\nInput: $AnsInput\nSecret: $AnsPass"
$DIALOG --msgbox "$out\nAttribs: $AnsCkLst\nNote: $AnsRadio" 20 60
done
#!/bin/bash
if (dialog --title "Message" --yesno "Want to do something risky?" 6 25)
# message box will have the size 25x6 characters
then
echo "Let's do something risky"
# do something risky
else
echo "Let's stay boring"
fi
echo -n "These files will be uploaded. Is this ok? (y/n) "
read yesno < /dev/tty
if [ "x$yesno" = "xy" ];then
# Yes
else
# No
fi
希望这有助于某人 .
3
是/否/取消
功能
#!/usr/bin/env bash
@confirm() {
local message="$*"
local result=''
echo -n "> $message (Yes/No/Cancel) " >&2
while [ -z "$result" ] ; do
read -s -n 1 choice
case "$choice" in
y|Y ) result='Y' ;;
n|N ) result='N' ;;
c|C ) result='C' ;;
esac
done
echo $result
}
用法
case $(@confirm 'Confirm?') in
Y ) echo "Yes" ;;
N ) echo "No" ;;
C ) echo "Cancel" ;;
esac
使用干净的用户输入确认
功能
#!/usr/bin/env bash
@confirm() {
local message="$*"
local result=3
echo -n "> $message (y/n) " >&2
while [[ $result -gt 1 ]] ; do
read -s -n 1 choice
case "$choice" in
y|Y ) result=0 ;;
n|N ) result=1 ;;
esac
done
return $result
}
用法
if @confirm 'Confirm?' ; then
echo "Yes"
else
echo "No"
fi
3
多选版本:
ask () { # $1=question $2=options
# set REPLY
# options: x=..|y=..
while $(true); do
printf '%s [%s] ' "$1" "$2"
stty cbreak
REPLY=$(dd if=/dev/tty bs=1 count=1 2> /dev/null)
stty -cbreak
test "$REPLY" != "$(printf '\n')" && printf '\n'
(
IFS='|'
for o in $2; do
if [ "$REPLY" = "${o%%=*}" ]; then
printf '\n'
break
fi
done
) | grep ^ > /dev/null && return
done
}
例:
$ ask 'continue?' 'y=yes|n=no|m=maybe'
continue? [y=yes|n=no|m=maybe] g
continue? [y=yes|n=no|m=maybe] k
continue? [y=yes|n=no|m=maybe] y
$
它会将 REPLY 设置为 y (在脚本中) .
5
在这种情况下,我曾多次使用 case 语句,使用案例陈述是一种很好的方法 . 利用布尔条件对 case 块进行封装的 while 循环可以实现,以便更好地控制程序,并满足许多其他要求 . 在满足所有条件后,可以使用 break 将控制权传递回程序的主要部分 . 此外,为了满足其他条件,当然可以添加条件语句以伴随控制结构: case 语句和可能的 while 循环 .
使用 case 语句来满足您的请求的示例
#! /bin/sh
# For potential users of BSD, or other systems who do not
# have a bash binary located in /bin the script will be directed to
# a bourne-shell, e.g. /bin/sh
# NOTE: It would seem best for handling user entry errors or
# exceptions, to put the decision required by the input
# of the prompt in a case statement (case control structure),
echo Would you like us to perform the option: "(Y|N)"
read inPut
case $inPut in
# echoing a command encapsulated by
# backticks (``) executes the command
"Y") echo `Do something crazy`
;;
# depending on the scenario, execute the other option
# or leave as default
"N") echo `execute another option`
;;
esac
exit
3
作为一行命令的朋友,我使用了以下内容:
while [ -z $prompt ]; do read -p "Continue (y/n)?" choice;case "$choice" in y|Y ) prompt=true; break;; n|N ) exit 0;; esac; done; prompt=;
写的longform,它的工作方式如下:
while [ -z $prompt ];
do read -p "Continue (y/n)?" choice;
case "$choice" in
y|Y ) prompt=true; break;;
n|N ) exit 0;;
esac;
done;
prompt=;
53
inquire () {
echo -n "$1 [y/n]? "
read answer
finish="-1"
while [ "$finish" = '-1' ]
do
finish="1"
if [ "$answer" = '' ];
then
answer=""
else
case $answer in
y | Y | yes | YES ) answer="y";;
n | N | no | NO ) answer="n";;
*) finish="-1";
echo -n 'Invalid response -- please reenter:';
read answer;;
esac
fi
done
}
... other stuff
inquire "Install now?"
...
$ get_yes_keypress "Here you cannot press enter. Do you like this [y/n]? "
Here you cannot press enter. Do you like this [y/n]? k
Here you cannot press enter. Do you like this [y/n]?
Here you cannot press enter. Do you like this [y/n]? n
$ echo $?
1
# Read a single char from /dev/tty, prompting with "$*"
# Note: pressing enter will return a null string. Perhaps a version terminated with X and then remove it in caller?
# See https://unix.stackexchange.com/a/367880/143394 for dealing with multi-byte, etc.
function get_keypress {
local REPLY IFS=
>/dev/tty printf '%s' "$*"
[[ $ZSH_VERSION ]] && read -rk1 # Use -u0 to read from STDIN
# See https://unix.stackexchange.com/q/383197/143394 regarding '\n' -> ''
[[ $BASH_VERSION ]] && </dev/tty read -rn1
printf '%s' "$REPLY"
}
# Get a y/n from the user, return yes=0, no=1 enter=$2
# Prompt using $1.
# If set, return $2 on pressing enter, useful for cancel or defualting
function get_yes_keypress {
local prompt="${1:-Are you sure [y/n]? }"
local enter_return=$2
local REPLY
# [[ ! $prompt ]] && prompt="[y/n]? "
while REPLY=$(get_keypress "$prompt"); do
[[ $REPLY ]] && printf '\n' # $REPLY blank if user presses enter
case "$REPLY" in
Y|y) return 0;;
N|n) return 1;;
'') [[ $enter_return ]] && return "$enter_return"
esac
done
}
# Credit: http://unix.stackexchange.com/a/14444/143394
# Prompt to confirm, defaulting to NO on <enter>
# Usage: confirm "Dangerous. Are you sure?" && rm *
function confirm {
local prompt="${*:-Are you sure} [y/N]? "
get_yes_keypress "$prompt" 1
}
# Prompt to confirm, defaulting to YES on <enter>
function confirm_yes {
local prompt="${*:-Are you sure} [Y/n]? "
get_yes_keypress "$prompt" 0
}
0
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
16
更通用的是:
function menu(){
title="Question time"
prompt="Select:"
options=("Yes" "No" "Maybe")
echo "$title"
PS3="$prompt"
select opt in "${options[@]}" "Quit/Cancel"; do
case "$REPLY" in
1 ) echo "You picked $opt which is option $REPLY";;
2 ) echo "You picked $opt which is option $REPLY";;
3 ) echo "You picked $opt which is option $REPLY";;
$(( ${#options[@]}+1 )) ) clear; echo "Goodbye!"; exit;;
*) echo "Invalid option. Try another one.";continue;;
esac
done
return
}
404
此解决方案读取单个字符并在yes响应上调用函数 .
read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
do_something
fi
2
yn() {
if [[ 'y' == `read -s -n 1 -p "[y/n]: " Y; echo $Y` ]];
then eval $1;
else eval $2;
fi }
yn 'echo yes' 'echo no'
yn 'echo absent no function works too!'
ans=''
while true; do
read -p "So is MikeQ the greatest or what (y/n/q) ?" -n1 ans
case ${ans,,} in
y|n|q) break;;
*) echo "Answer y for yes / n for no or q for quit.";;
esac
done
echo -e "\nAnswer = $ans"
if [[ "${ans,,}" == "q" ]] ; then
echo "OK Quitting, we will assume that he is"
exit 0
fi
if [[ "${ans,,}" == "y" ]] ; then
echo "MikeQ is the greatest!!"
else
echo "No? MikeQ is not the greatest?"
fi
27 回答
我注意到没有人发布一个答案显示多行回显菜单这样简单的用户输入所以这是我的去处:
发布此方法是希望有人可能觉得它有用且节省时间 .
这是我放在一起的东西:
我是一个初学者,所以带上一粒盐,但似乎有效 .
使用最少行数实现此目的的最简单方法如下:
if
只是一个例子:由你来决定如何处理这个变量 .为此,Bash有select .
受到@Mark和@Myrddin的答案的启发,我创建了这个函数用于通用提示
像这样用它:
使用
read
命令:然后你需要的所有其他东西
我建议你use dialog ......
它简单易用,还有一个名为gdialog的gnome版本,它采用完全相同的参数,但在X上显示了它的GUI样式 .
在shell提示符下获取用户输入的最简单且最广泛可用的方法是read命令 . 说明其用法的最佳方式是一个简单的演示:
Steven Huwig指出的另一种方法是Bash的select命令 . 以下是使用
select
的相同示例:使用
select
,如果它们提供无效输入,则不需要while true
循环重试 .另外,请查看F. Hauri的excellent answer .
你想:
Bash内置命令(即便携式)
检查TTY
默认答案
超时
有色问题
片段
解释
[[ -t 0 ]] && read ...
=>如果是TTY,则调用命令read
read -n 1
=>等一个字符$'\e[1;32m ... \e[0m '
=>以绿色打印(绿色很好,因为白色/黑色背景都可读)
[[ $do_xxxx =~ ^(y|Y|)$ ]]
=> bash正则表达式超时=>默认答案为否
一种简单的方法是使用
xargs -p
或gnuparallel --interactive
.我更喜欢xargs的行为,因为它像其他交互式unix命令一样在提示之后立即执行每个命令,而不是收集在末尾运行的yes . (通过你想要的那些之后你可以用Ctrl-C . )
例如 . ,
一个通用问题至少有五个答案 .
取决于
符合
posix:可以在具有通用shell环境的不良系统上运行
bash具体:使用所谓的bashisms
如果你想要的话
simple``inline''问题/答案(通用解决方案)
非常格式化的接口,如ncurses或更多图形使用libgtk或libqt ...
使用强大的readline历史记录功能
1. POSIX通用解决方案
您可以使用
read
命令,然后使用if ... then ... else
:#if echo“$ answer”| grep -iq“^ y”;然后
(感谢Adam Katz's comment:将上面的测试替换为更便携的测试并避免使用一个分叉:)
POSIX,但是单一的关键功能
但如果您不希望用户必须点击Return,您可以写:
( Edited: 正如@JonathanLeffler正确地建议的那样,保存stty的配置可能比简单地强迫他们理智更好 . )
Note: 这是在sh,bash,ksh,dash和busybox下测试的!
相同,但明确等待y或n:
使用专用工具
有许多工具是使用
libncurses
,libgtk
,libqt
或其他图形库构建的 . 例如,使用whiptail
:根据您的系统,您可能需要将
whiptail
替换为另一个类似的工具:其中
20
是对话框的行数高度,60
是对话框的宽度 . 这些工具都具有几乎相同的语法 .2. Bash特定解决方案
基本在线方法
我更喜欢使用
case
所以我甚至可以测试yes | ja | si | oui
如果需要的话......符合单键功能
在bash下,我们可以为
read
命令指定预期输入的长度:在bash下,
read
命令接受超时参数,这可能很有用 .专用工具的一些技巧
更复杂的对话框,超出简单的
yes - no
目的:进度条:
小演示:
更多样品?看看Using whiptail for choosing USB device和USB removable storage selector: USBKeyChooser
5.使用readline的历史记录
例:
这将在您的
$HOME
目录中创建一个比您可以使用的文件.myscript.history
readline的历史命令,如Up,Down,Ctrl r等 .要获得一个很好的类似ncurses的输入框,请使用命令 dialog ,如下所示:
默认情况下,对话框软件包至少安装在SUSE Linux中 .
-e
选项使用户可以使用箭头键编辑输入 .如果您想使用建议作为输入:
-i
选项打印一个暗示输入 .您可以使用内置的read命令;使用
-p
选项提示用户提问 .从BASH4开始,您现在可以使用
-i
来建议答案,因此用户只需按return
即可输入:(但请记住使用"readline"选项
-e
以允许使用箭头键进行行编辑)如果你想要一个“是/否”逻辑,你可以这样做:
很抱歉在这么老的帖子上发帖 . 几周前我遇到了类似的问题,在我的情况下,我需要一个解决方案,它也可以在一个在线安装程序脚本中工作,例如:
curl -Ss https://raw.github.com/_____/installer.sh | bash
使用
read yesno < /dev/tty
对我来说很好:希望这有助于某人 .
是/否/取消
功能
用法
使用干净的用户输入确认
功能
用法
多选版本:
例:
它会将
REPLY
设置为y
(在脚本中) .在这种情况下,我曾多次使用
case
语句,使用案例陈述是一种很好的方法 . 利用布尔条件对case
块进行封装的while
循环可以实现,以便更好地控制程序,并满足许多其他要求 . 在满足所有条件后,可以使用break
将控制权传递回程序的主要部分 . 此外,为了满足其他条件,当然可以添加条件语句以伴随控制结构:case
语句和可能的while
循环 .使用
case
语句来满足您的请求的示例作为一行命令的朋友,我使用了以下内容:
写的longform,它的工作方式如下:
仅限单键按键
这是一个更长但可重复使用的模块化方法:
返回
0
=是和1
=否无需按Enter键 - 只需一个字符
可以按Enter键接受默认选项
可以禁用默认选项以强制选择
适用于
zsh
和bash
.按Enter键时默认为“no”
请注意
N
是大写的 . 按Enter键,接受默认值:另请注意,
[y/N]?
已自动附加 . 接受默认"no",因此不会回显任何内容 .Re-prompt until a valid response is given:
按Enter键时默认为“是”
请注意
Y
是大写的:上面,我只是按了回车键,所以命令运行了 .
无输入默认值 - 要求y或n
这里返回了
1
或false . 请注意,使用此较低级别的功能,您需要提供自己的[y/n]?
提示 .代码
更通用的是:
此解决方案读取单个字符并在yes响应上调用函数 .
回应他人:
您不需要在BASH4中指定大小写,只需使用',,'来制作var小写 . 另外,我强烈不喜欢将代码放入读取块内部,获取结果并在读取块IMO之外处理它 . 还包括退出IMO的'q' . 最后为什么键入'yes'只需使用-n1并按y键 .
示例:用户可以按y / n,也可以按q退出 .