我试图创建一个菜单,允许用户在当前目录中调用某些shell脚本。菜单循环,直到用户退出脚本(输入5)
下面是我的代码:until [ "$SELECTION" = "5" ]; do
echo "# Enter a number to launch:"
echo "# 1) Script 1"
echo "# 2) Script 2"
echo "# 3) Script 1 and Script 2"
echo "# 4) Readme"
echo "# 5) Exit"
echo -n "Launch: "
read SELECTION
case $SELECTION in
1)
(exec "./script1") ;;
2)
(exec "./script2") ;;
3)
(exec "./script1")
(exec "./script2") ;;
4) vi "readme.txt" ;;
5) exit 0 ;;
*) echo "Error. Please enter a valid selection." ;;
esac
done
在用户选择之后,所选脚本运行良好,但是一旦完成,我得到一个重复的错误:
read: read error: 0: Resource temporarily unavailable
它永远不会返回到菜单。我不知道我做错了什么。什么好主意吗?
看看你的菜单,有一些东西没有意义。在每个case语句中调用:
(exec "./script1")
将./script1
作为命令调用,而不是单独的脚本。其次,由于您将行括在父()
中,因此您强制执行在子shell中而不是当前shell中进行。
您在[ "$SELECTION" = "5" ]
中使用的SELECTION
似乎未初始化,(我认为这是您将其包装在引号中的原因)。引号没有错,但你的值是1-5
,所以它不是强制性的,只要它是初始化的。
你的菜单本身很好。事实是,它未能执行多次是你在(exec "./script1")
所做的任何结果。由于您似乎试图从case
语句调用bash脚本,因此启动脚本(如果它们不能使用chmod 0755
执行)的正确方法是使用bash
而不是exec
。如果脚本不是bash,或者您希望泛化调用,那么使用exec
将像注释中提到的那样工作。
虽然until
没有什么问题(除了不常用),我建议使用while
。此外,由于一行中有多个echo
语句,因此可以考虑使用here
语句来创建heredoc
。
代码的缩进使阅读更容易,并保持逻辑清晰。需要注意的是heredoc
和它的结束分隔符。要缩进heredoc
及其分隔符,它们必须与TABS
而不是SPACES
缩进。此外,heredoc必须以<<-
开始,而不是简单地以<<
开始,以利用TAB
缩进。(这就是为什么我一开始没有提出这个问题的原因)
可能看起来像下面这样。注意:下面的代码是8-space
缩进的,因为SO将TABS
转换为SPACES
,所以要使用显示缩进的代码,您需要确保代码前面的空白是TAB
字符而不是SPACES
字符,否则将不会运行:
declare -i SEL=0
while [ $SEL != 5 ]; do
cat >&2 <<- MENU
Enter a number to launch:
1) Script 1
2) Script 2
3) Script 1 and Script 2
4) Readme
5) Exit
MENU
echo -n " Launch: "
read SEL
case $SEL in
1) echo "./script1"
;;
2) echo "./script2"
;;
3) echo "./script1"
echo "./script2"
;;
4) vi "readme.txt"
;;
5) exit 0
;;
*) echo "Error. Please enter a valid selection."
;;
esac
done
您可以选择是否要正式缩进heredoc
。我更喜欢4-space
缩进,所以我只保留heredoc
开头和分隔符而不缩进,以保留允许剪切/粘贴示例的的能力。你的选择:
declare -i SEL=0
while [ $SEL != 5 ]; do
cat >&2 << MENU
Enter a number to launch:
1) Script 1
2) Script 2
3) Script 1 and Script 2
4) Readme
5) Exit
MENU
echo -n " Launch: "
read SEL
case $SEL in
1) exec "./script1"
;;
2) exec "./script2"
;;
3) exec "./script1"
exec "./script2"
;;
4) vi "readme.txt"
;;
5) exit 0
;;
*) echo "Error. Please enter a valid selection."
;;
esac
done