Myr*_*rys 1514
在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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
随着select
你并不需要净化输入-它显示可用的选项,你键入相应的你的选择一个号码.它也会自动循环,因此while true
如果它们提供无效输入,则无需重试循环.
另外,请查看F. Hauri 的优秀答案.
F. *_*uri 487
取决于
如果你想要的话
您可以使用该read
命令,然后执行以下操作if ... then ... else
:
echo -n "Is this a good question (y/n)? "
read answer
Run Code Online (Sandbox Code Playgroud)
# if echo "$answer" | grep -iq "^y" ;then
Run Code Online (Sandbox Code Playgroud)
if [ "$answer" != "${answer#[Yy]}" ] ;then
echo Yes
else
echo No
fi
Run Code Online (Sandbox Code Playgroud)
(感谢Adam Katz的评论:将上面的测试替换为一个更便携的测试并避免使用一个分叉:)
但如果您不希望用户必须点击Return,您可以写:
(编辑:正如@JonathanLeffler正确地建议的那样,保存 stty的配置可能比仅仅强迫他们理智更好.)
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
Run Code Online (Sandbox Code Playgroud)
注意:这是在sh,bash,ksh,dash和busybox下测试的!
相同,但明确等待y或n:
#/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
Run Code Online (Sandbox Code Playgroud)
有很多其使用内置的工具libncurses
,libgtk
,libqt
或其他图形库.例如,使用whiptail
:
if whiptail --yesno "Is this a good question" 20 60 ;then
echo Yes
else
echo No
fi
Run Code Online (Sandbox Code Playgroud)
根据您的系统,您可能需要更换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
Run Code Online (Sandbox Code Playgroud)
20
对话框的高度在哪里,行数60
是对话框的宽度.这些工具都具有几乎相同的语法.
DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...
Run Code Online (Sandbox Code Playgroud)
read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
y|Y )
echo Yes
;;
* )
echo No
;;
esac
Run Code Online (Sandbox Code Playgroud)
我更喜欢使用,case
所以yes | ja | si | oui
如果需要我甚至可以测试......
在bash下,我们可以为read
命令指定预期输入的长度:
read -n 1 -p "Is this a good question (y/n)? " answer
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
除了简单的yes - no
目的之外,更复杂的对话框:
dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe
Run Code Online (Sandbox Code Playgroud)
进度条:
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
)
Run Code Online (Sandbox Code Playgroud)
小演示:
#!/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
Run Code Online (Sandbox Code Playgroud)
更多样品?看看使用whiptail选择USB设备和USB可移动存储选择器:USBKeyChooser
例:
#!/bin/bash
set -i
HISTFILE=~/.myscript.history
history -c
history -r
myread() {
read -e -p '> ' $1
history -s ${!1}
}
trap 'history -a;exit' 0 1 2 3 6
while myread line;do
case ${line%% *} in
exit ) break ;;
* ) echo "Doing something with '$line'" ;;
esac
done
Run Code Online (Sandbox Code Playgroud)
这将创建一个文件.myscript.history
在$HOME
目录中,比你能使用输入行的历史命令,比如Up, Down,Ctrl+ r等.
Pis*_*tos 348
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
Run Code Online (Sandbox Code Playgroud)
yPh*_*hil 163
您可以使用内置的read命令; 使用该-p
选项可向用户提示问题.
从BASH4开始,您现在可以使用-i
建议答案,因此用户只需按下-e
即可输入:
read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH
Run Code Online (Sandbox Code Playgroud)
(但请记住使用"readline"选项-p
允许使用箭头键进行行编辑)
如果你想要一个"是/否"逻辑,你可以这样做:
read -e -p "
List the content of your home dir ? [Y/n] " YN
[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
Run Code Online (Sandbox Code Playgroud)
Ste*_*wig 105
Bash已经选择了这个目的.
select result in Yes No Cancel
do
echo $result
done
Run Code Online (Sandbox Code Playgroud)
小智 56
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
Run Code Online (Sandbox Code Playgroud)
mpe*_*pen 36
这是我放在一起的东西:
#!/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
Run Code Online (Sandbox Code Playgroud)
我是一个初学者,所以带上一粒盐,但似乎有效.
小智 32
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?"
...
Run Code Online (Sandbox Code Playgroud)
oli*_*bre 27
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
Run Code Online (Sandbox Code Playgroud)
[[ -t 0 ]] && read ...
=> read
如果TTY,则调用命令read -n 1
=>等一个字符$'\e[1;32m ... \e[0m '
=>以绿色打印[[ $do_xxxx =~ ^(y|Y|)$ ]]
=> bash正则表达式do_xxxx=y
[[ -t 0 ]] && { # Timeout 5 seconds (read -t 5)
read -t 5 -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx || # read 'fails' on timeout
do_xxxx=n ; } # Timeout => answer No
if [[ $do_xxxx =~ ^(y|Y|)$ ]]
then
xxxx
fi
Run Code Online (Sandbox Code Playgroud)
Apu*_*kar 24
使用最少行数实现此目的的最简单方法如下:
read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;
if [ "$CONDITION" == "y" ]; then
# do something here!
fi
Run Code Online (Sandbox Code Playgroud)
这if
只是一个例子:由你决定如何处理这个变量.
小智 18
使用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
Run Code Online (Sandbox Code Playgroud)
然后你需要的所有其他东西
Den*_*nis 17
此解决方案读取单个字符并在yes响应上调用函数.
read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
do_something
fi
Run Code Online (Sandbox Code Playgroud)
Léa*_*ris 16
可以在 POSIX shell 中处理语言环境感知的“是/否选择”;通过使用LC_MESSAGES
locale 类别的条目,witch 提供了现成的 RegEx 模式来匹配输入,以及用于本地化 Yes No 的字符串。
#!/usr/bin/env sh
# Getting LC_MESSAGES values into variables
# shellcheck disable=SC2046 # Intended IFS splitting
IFS='
' set -- $(locale LC_MESSAGES)
yesexpr="$1"
noexpr="$2"
yesstr="$3"
nostr="$4"
messages_codeset="$5" # unused here, but kept as documentation
# Display Yes / No ? prompt into locale
echo "$yesstr / $nostr ?"
# Read answer
read -r yn
# Test answer
case "$yn" in
# match only work with the character class from the expression
${yesexpr##^}) echo "answer $yesstr" ;;
${noexpr##^}) echo "answer $nostr" ;;
esac
Run Code Online (Sandbox Code Playgroud)
编辑:正如@Urhixidur在他的评论中提到的:
不幸的是,POSIX 只指定了前两个(yesexpr 和 noexpr)。在 Ubuntu 16 上, yesstr 和 nostr 为空。
参见:https : //www.ee.ryerson.ca/~courses/ele709/susv4/xrat/V4_xbd_chap07.html#tag_21_07_03_06
LC_MESSAGES
在
yesstr
与nostr
现场的关键字和YESSTR
和NOSTR
langinfo项目以前用于匹配用户的肯定和否定响应。在 POSIX.1-2008 中yesexpr
,noexpr
、YESEXPR
、 和NOEXPR
扩展正则表达式已经取代了它们。应用程序应该使用基于区域设置的通用消息传递工具来发出提示消息,其中包括示例所需的响应。
或者以 Bash 方式使用语言环境:
#!/usr/bin/env bash
IFS=$'\n' read -r -d '' yesexpr noexpr _ < <(locale LC_MESSAGES)
printf -v yes_or_no_regex "(%s)|(%s)" "$yesexpr" "$noexpr"
printf -v prompt $"Please answer Yes (%s) or No (%s): " "$yesexpr" "$noexpr"
declare -- answer=;
until [[ "$answer" =~ $yes_or_no_regex ]]; do
read -rp "$prompt" answer
done
if [[ -n "${BASH_REMATCH[1]}" ]]; then
echo $"You answered: Yes"
else
echo $"No, was your answer."
fi
Run Code Online (Sandbox Code Playgroud)
使用语言环境提供的正则表达式匹配答案。
要翻译剩余的消息,请使用bash --dump-po-strings scriptname
输出 po 字符串以进行本地化:
#: scriptname:8
msgid "Please answer Yes (%s) or No (%s): "
msgstr ""
#: scriptname:17
msgid "You answered: Yes"
msgstr ""
#: scriptname:19
msgid "No, was your answer."
msgstr ""
Run Code Online (Sandbox Code Playgroud)
Jah*_*hid 12
read -e -p "Enter your choice: " choice
Run Code Online (Sandbox Code Playgroud)
该-e
选项使用户可以使用箭头键编辑输入.
如果您想使用建议作为输入:
read -e -i "yes" -p "Enter your choice: " choice
Run Code Online (Sandbox Code Playgroud)
-i
选项打印暗示输入.
Wal*_*r A 12
您可以在REPLY
上使用默认值read
,将其转换为小写并与带有表达式的一组变量进行比较。
该脚本还支持ja
/ si
/oui
read -rp "Do you want a demo? [y/n/c] "
[[ ${REPLY,,} =~ ^(c|cancel)$ ]] && { echo "Selected Cancel"; exit 1; }
if [[ ${REPLY,,} =~ ^(y|yes|j|ja|s|si|o|oui)$ ]]; then
echo "Positive"
fi
Run Code Online (Sandbox Code Playgroud)
Eri*_*kis 11
这个问题有很多好的答案,但从我看来,没有一个是我的理想答案,即:
这是我的版本,它具有这些属性:
read -n1 -p "Continue? (Y/n) " confirm
if ! echo $confirm | grep '^[Yy]\?$'; then
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
您可以将该条件修改为仅在“yes”上运行(只需删除!
语句中的if
)或添加else
if 您想在两个分支上运行代码。
use*_*932 10
很抱歉在这么老的帖子上发帖.几周前我遇到了类似的问题,在我的情况下,我需要一个解决方案,它也可以在一个在线安装程序脚本中工作,例如:curl -Ss https://raw.github.com/_____/installer.sh | bash
使用read yesno < /dev/tty
对我来说很好:
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
Run Code Online (Sandbox Code Playgroud)
希望这有助于某人.
Ctr*_*l-C 10
单线:
\nread -p "Continue? [Enter] \xe2\x86\x92 Yes, [Ctrl]+[C] \xe2\x86\x92 No."\n
Run Code Online (Sandbox Code Playgroud)\n这假设“否”和“取消”具有相同的结果,因此没有理由以不同的方式对待它们。
\n要获得一个很好的类似ncurses的输入框,请使用如下命令对话框:
#!/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
Run Code Online (Sandbox Code Playgroud)
默认情况下,对话框软件包至少安装在SUSE Linux中.
这是一个更长,但可重复使用和模块化的方法:
0
=是和1
=否zsh
和bash
.请注意,这N
是资本.按Enter键,接受默认值:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?
Run Code Online (Sandbox Code Playgroud)
另请注意,这[y/N]?
是自动附加的.接受默认的"no",因此不会回显任何内容.
重新提示,直到给出有效的回复:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *
Run Code Online (Sandbox Code Playgroud)
请注意,Y
大写:
$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *
Run Code Online (Sandbox Code Playgroud)
上面,我只是按了回车键,所以命令运行了.
y
或n
$ 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
Run Code Online (Sandbox Code Playgroud)
在这里,1
或者返回false.请注意,使用此较低级别的功能,您需要提供自己的[y/n]?
提示.
# 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
}
Run Code Online (Sandbox Code Playgroud)
我注意到没有人发布这样一个简单的用户输入显示多行回显菜单的答案,因此我可以这样做:
#!/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
Run Code Online (Sandbox Code Playgroud)
发布此方法是为了希望有人发现它有用且节省时间。
检查这个
read -p "Continue? (y/n): " confirm && [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]] || exit 1
Run Code Online (Sandbox Code Playgroud)
我建议你使用对话框...
Linux 学徒:使用对话框改进 Bash Shell 脚本
对话框命令允许在 shell 脚本中使用窗口框,从而使其使用更具交互性。
它简单易用,还有一个名为 gdialog 的 gnome 版本,它采用完全相同的参数,但在 X 上显示 GUI 风格。
多选版本:
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
}
Run Code Online (Sandbox Code Playgroud)
例子:
$ 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
$
Run Code Online (Sandbox Code Playgroud)
它将设置REPLY
为y
(在脚本内)。
受到@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
}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
Run Code Online (Sandbox Code Playgroud)