我想暂停shell脚本中的输入,并提示用户进行选择,例如标准的“是”、“否”或“取消”类型的问题。在典型的bash提示符下,如何实现这一点?
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!'
yn(){ read -s -n 1 -p '[y/n]'; test "$REPLY" = "y" ; } yn && echo success || echo failure
。 - tripleee一个简单的方法是使用xargs -p
或gnu parallel --interactive
。
我更喜欢使用xargs,因为它的行为更好,它像其他交互式Unix命令一样立即在提示符后执行每个命令,而不是在最后收集确认来运行。(你可以在完成你想要的操作后按Ctrl-C。)
例如:
echo *.xml | xargs -p -n 1 -J {} mv {} backup/
xargs --interactive
只能回答是或否。只要这就是你所需要的,那么这就足够了,但是我的原始问题给出了三种可能的结果。我真的很喜欢它可以流式传输;许多常见的场景都可以从它的管道能力中受益。 - Myrddin Emryscase
语句,使用case
语句是一个不错的方法。可以实现一个while
循环来封装case
块,并利用布尔条件来控制程序,以满足更多的要求。当所有条件都满足时,可以使用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
回复其他人:
BASH4中不需要指定大小写,只需使用',,'将变量转换为小写即可。此外,我强烈反对在read块内放置代码,最好在read块外处理结果。还可以包含一个“q”以退出程序。最后,为什么要输入“yes”,只需使用-n1并按y键即可。
示例:用户可以按y / n键,也可以按q键退出。
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
使用 PyInquirer 实现的一个Python
单行代码替代方案
python3 -c 'import PyInquirer; print(PyInquirer.prompt([{"type":"confirm", "message":"Do you want to continue?", "name":"r"}]).get("r"))'
该程序支持是/否/取消 (按键intr, CTRL+C)。
confirm() {
local ans IFS=;
while read -rp "$1" -n1 ans;
do printf '\n';
case $ans in [Yy]) return 0;;
[Nn]) return 1;;
esac;
done;
}; ## Usage: if confirm "Are you sure? "; then ...
if confirm "Does everything look ok...reboot now? [Y/n]"; then
echo "rebooting..."
sleep 5
reboot
fi
#!/bin/bash
if ! getans.sh 'Shall we proceed?' y ; then
echo "User said “NO”"
exit 1
fi
echo "User said “YES”"
# do something usefull
exit 0
y
/Y
确认,其他任何输入都会中止。#!/usr/bin/env bash
set -eu -o pipefail
function prompt() {
read -p "$* [Y/n]: " yn
if [[ $yn = "y" || $yn = "Y" ]]; then
return 0
else
return 1
fi
}
prompt "one liner?" && echo "YES" || echo "NO"
if prompt "in an if?"; then
echo "YES"
else
echo "NO"
fi
我创建了这个函数,以便由我所有需要是yes/no/true/false/default响应的bash脚本调用,因为我厌倦了每次需要响应时都重新创建代码。
它具有可设置的问题和可设置的默认答案,对于默认响应也有错误处理(意味着您可以更改默认答案),同时捕获未被引号包围的问题。我意识到这比原始帖子要求的更详细,但在任何bash 4+中,它应该是完全可移植的。它也可以作为if语句中的命令使用,因为它返回0或1,并详细说明了答案以进行调试。
用法:confirm -d n "是否是答案?"
返回输出:
user@ubuntu# confirm -d n "Is this the answer?"
Is this the answer? [Y/n:default=N]:
default no
这是函数:
confirm(){
errorMsg='
Too many arguments.
use "-d" as the first option to set default value.
If providing a question, remember to quote the line to prevent each word from being an argument.
example: confirm -d n "Is this the answer?"'
defSet=false
while [ "$#" -ge 1 ]; do
if [ "$#" -ge 2 ]; then
confirmArg=$1
if [[ "$confirmArg" = '-d' ]]; then
confirmArgCheck=$2
errorMsg2="
'${confirmArgCheck}' is not a valid default return value.
Must be [Yy]es/[Nn]o or [Tt]rue/[Ff]alse"
case $confirmArgCheck in
[Yy]*|[Tt]*)
regex1="[Yy][Ee]?[Ss]?$"
regex2="[Tt][Rr]?[Uu]?[Ee]?$"
if [[ "$confirmArgCheck" =~ $regex1 ]]; then
unset regex1 && unset regex2
confirmArgVal=Y
elif [[ "$confirmArgCheck" =~ $regex2 ]]; then
unset regex1 && unset regex2
confirmArgVal=Y
else
unset regex1 && unset regex2
echo "$errorMsg2"
return 1
fi
;;
[Nn]*|[Ff]*)
regex1="[Nn][Oo]?$"
regex2="[Ff][Aa]?[Ll]?[Ss]?[Ee]?$"
if [[ "$confirmArgCheck" =~ $regex1 ]]; then
unset regex1 && unset regex2
confirmArgVal=N
elif [[ "$confirmArgCheck" =~ $regex2 ]]; then
unset regex1 && unset regex2
confirmArgVal=N
else
unset regex1 && unset regex2
echo "$errorMsg2"
return 1
fi
;;
*)
echo "$errorMsg2"
return 1
;;
esac
defSet=true
shift 2
else
if [[ ! "$*" == *"-d"* ]]; then
shiftmore="$#"
quest="$@"
questSet=true
shift "$shiftmore"
else
echo "$errorMsg"
return 1
fi
fi
else
quest=$1
questSet=true
shift 1
fi
done
if [[ ! $defSet = true ]]; then
confirmArgVal=Y
fi
if [[ ! $questSet = true ]]; then
quest='Answer?'
fi
while true; do
read -r -p "${quest} [Y/n:default=$confirmArgVal]: " yn
case $yn in
[Yy]*)
unset quest
unset yn
unset confirmArgVal
echo "answered yes"
return 0
;;
[Nn]*)
unset quest
unset yn
unset confirmArgVal
echo "answered no"
return 1
;;
"")
unset quest
unset yn
if [[ "$confirmArgVal" = 'Y' ]]; then
unset confirmArgVal
echo "default yes"
return 0
else
unset confirmArgVal
echo "default no"
return 1
fi
;;
*)
echo "Please answer yes or no."
;;
esac
done
}
[yn]
选项,则大写字母是默认值。即[Yn]
默认为“yes”,[yN]
默认为“no”。请参见https://ux.stackexchange.com/a/40445/43532 - Tyzoidread
命令进行提示。 - smac89bash
中暂停的规范方式。提供的结果可以轻松转移。 - Cadoiz