试图找出一种在case语句中返回的方法。例如,如果你运行....
while :
do
clear
cat<<-EOF
======================
Foo Bar Doo Dah Setup
======================
(1) Foo
(2) Bar
(q) Quit
----------------------
EOF
read
case $REPLY in
"1") foo="foo" ;;
"2") bar="bar" ;;
"q") break ;;
* ) echo "Invalid Option"
esac
sleep .5
clear
cat<<-EOF
======================
Foo Bar Doo Dah Setup
======================
(1) Doo
(2) Dah
(q) Quit
----------------------
EOF
read
case $REPLY in
"1") doo="doo" ;;
"2") dah="dah" ;;
"q") break ;;
* ) echo "Invalid Option"
esac
sleep .5
done
...并输入&#34;无效选项&#34;那么你会发现它会转移到下一个案例,而不是重新评估案例。
解决方法并不是太糟糕,只需要将case语句嵌套到while循环中的if语句中......
while read; do
if [ $REPLY -ge 1 -a $REPLY -le 2 ]; then
case $REPLY in
"1") foo="foo" ;;
"2") bar="bar" ;;
esac
break
elif [ $REPLY == q ]; then
break
else
echo "Invalid Option"
fi
done
所说的似乎有点多,有人知道某些形式的循环控件从案例选择中重新运行案例陈述吗?
答案 0 :(得分:3)
如果在继续下一个菜单之前需要菜单中的有效选项,那么您需要围绕选择过程进行循环。您可能还应计算失败并在连续几次失败后终止,例如10。
shell循环结构支持break
和continue
,并且可以选择后跟一个数字,表示应该断开多少循环级别(默认级别数为1)。
代码还应注意read
检测到的EOF并终止循环。这是通过以下代码中的answer
变量实现的。
这导致代码如下:
retries=0
max_retries=10
while [ $retries -lt $max_retries ]
do
clear
cat <<-'EOF'
======================
Foo Bar Doo Dah Setup
======================
(1) Foo
(2) Bar
(q) Quit
----------------------
EOF
retries=0
answer=no
while read
do
case "$REPLY" in
"1") foo="foo"; answer=yes; break;;
"2") bar="bar"; answer=yes; break;;
"q") break 2;; # Or exit, or return if the code is in a function
* ) echo "Invalid Option ('$REPLY' given)" >&2
if [ $((++retries)) -ge $max_retries ]; then break 2; fi
;;
esac
done
if [ "$answer" = "no" ]; then break; fi # EOF in read loop
sleep .5
clear
cat <<-'EOF'
======================
Foo Bar Doo Dah Setup
======================
(1) Doo
(2) Dah
(q) Quit
----------------------
EOF
retries=0
answer=no
while read
do
case $REPLY in
"1") doo="doo"; answer=yes;;
"2") dah="dah"; answer=yes;;
"q") break 2;;
* ) echo "Invalid Option ('$REPLY' given)"" >&2
if [ $((++retries)) -ge $max_retries ]; then break 2; fi
;;
esac
done
if [ "$answer" = "no" ]; then break; fi # EOF in read loop
sleep .5
echo "$foo$bar $doo$dah" # Do something with the entered information
done
我并不完全热衷read
之后没有名字,尤其是因为它是Bash扩展而不是标准shell功能(POSIX read
实用程序不提供默认值变量名称),省略名称会不必要地限制脚本的可移植性。
另请注意,here文档的开头标记用引号括起来,因此here文档的内容不受shell扩展的影响。 -
表示从此文档和文档标记行的末尾删除了前导标签(但不是空格)。
第一个循环的问题中的代码也可以被修复&#39;使用continue
而不是嵌套的while
循环。但是,如果第二个循环只是重试第二个提示,继续外循环并跳过第一个菜单会很复杂。显示的解决方案是对称的,并且适当地隔离了两个提示中每个提示的输入。
我选择不在重试时重新回显菜单,但是也不难在这个代码上循环。使用:
是可行的retries=0
answer=no
while clear
cat <<-'EOF'
======================
Foo Bar Doo Dah Setup
======================
(1) Foo
(2) Bar
(q) Quit
----------------------
EOF
read
do
…processing $REPLY as before…
done
然而,这样做会导致许多人头疼,因为人们通常不会意识到在while
语句之后你可以拥有一个命令列表,并且它只是控制循环是否继续的最后一个的退出状态是否是另一次迭代。
我个人避免使用shell脚本中的标签,因此我可能会创建变量来保存菜单:
menu1=$(cat <<-'EOF'
======================
Foo Bar Doo Dah Setup
======================
(1) Foo
(2) Bar
(q) Quit
----------------------
EOF
)
循环中的提示可能是:
while clear; echo "$menu1"; read
更容易理解(双引号至关重要)。如果&&
命令运行良好并且退出成功,则可以使用;
代替clear
。