我正在尝试创建一个菜单,允许用户在当前目录中调用某些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
它永远不会返回菜单。 我不确定我做错了什么。有任何想法吗?这是在bash。
答案 0 :(得分:2)
查看菜单有一些不合理的事情。在您的每个案例陈述中,您都可以致电:
(exec "./script1")
这是将./script1
称为命令,而不是单独的脚本。第二,因为你将这一行括在parens ()
中,你强迫执行在子shell 而不是当前的shell中。
您在SELECTION
中使用[ "$SELECTION" = "5" ]
似乎未初始化,(我认为这是您将其包含在引号中的原因)。引用没有错,但您的值为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