Bash 打印出开关所有外壳的列表
奇怪的问题。是否可以在bash中自动打印某个开关箱的所有箱?在某种程度上,它尽可能保持可维护性,这意味着如果添加了新的案例来打印相同的案例,则不必再添加任何代码Bash 打印出开关所有外壳的列表,bash,Bash,奇怪的问题。是否可以在bash中自动打印某个开关箱的所有箱?在某种程度上,它尽可能保持可维护性,这意味着如果添加了新的案例来打印相同的案例,则不必再添加任何代码 例如,如果案例表示命令,这将非常有用。然后,帮助功能可以打印出所有可用的命令 不知道我是否正确理解了您的问题,但您可以做一些事情,例如打印所有可用案例作为默认选择: case "$1" in start) start ;; stop) stop ;;
例如,如果案例表示命令,这将非常有用。然后,帮助功能可以打印出所有可用的命令 不知道我是否正确理解了您的问题,但您可以做一些事情,例如打印所有可用案例作为默认选择:
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status anacron
;;
restart)
stop
start
;;
condrestart)
if test "x`pidof anacron`" != x; then
stop
start
fi
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status}"
exit 1
esac
bash
不允许您访问它解析的令牌,也不保存case
字符串(也可以是glob表达式)
不幸的是,这意味着您将无法按希望的方式干燥代码。没有直接的方法来实现这一点,但您可以使用数组来维护您的选择:
# Define your choices - be sure not to change their order later; only
# *append* new ones.
choices=( foo bar baz )
# Make the array elements the case branches *in order*.
case "$1" in
"${choices[0]}")
echo 'do foo'
;;
"${choices[1]}")
echo 'do bar'
;;
"${choices[2]}")
echo 'do baz'
;;
*)
echo "All choices: ${choices[@]}"
esac
这会降低分支的可读性,但如果仔细维护阵列,这是一个可管理的解决方案
注意分支条件是如何包含在“…”
中的,以防止shell将值解释为(类全局)模式
也就是说,正如所指出的,您可能希望将您的选择定义为模式,以匹配字符串的变化:
在这种情况下:
- 在
数组中用引号定义模式;e、 例如,选项
choices=(foo-bar-baz'h*)
- 在
分支中引用它;e、 例如,案例
${choices[3]}
#!/bin/bash
set -euo pipefail
# create coprocess with 2 descriptors so we can read and write to them
coproc CAT { cat ; }
# creme de la creme of this solution - use function to both collect and select elements
function element {
echo "$1" >&${CAT[1]}
echo "$1"
}
case "$1" in
$(element A))
echo "Your choice is: A"
;;
$(element B))
echo "Your choice is: B"
;;
*)
echo "Your choice is not present in available options: $1"
# close writing descriptor
exec {CAT[1]}>&-
#read colected options into an array
mapfile -t OPTIONS <&${CAT[0]}
echo "Available options are: [ ${OPTIONS[@]} ]"
;;
esac
此解决方案分为两部分:
-它创建用于从子shell读取和写入的子进程coproc
- 函数
,它既写入元素
子进程的描述符,又返回它的参数,因此我们可以在coproc
案例中使用它。。。esac
案例
之外进行,那么您可以使用&case
语句的code>特性,它强制检查case
中的每个语句(通常-即;
-在第一次匹配后停止)。需要进行此检查,以便稍后将所有选项收集到一个数组中
不使用此选项可能有很多原因(可以安全存储在描述符中的数据限制,而不必读取它们),我欢迎所有可以使此解决方案更好的注释。您可以让脚本自行检查:
#/bin/bash
案例#开始=$(“$LINENO”+2))#开始的存储行号
案件“$1”
简单案例)呼应“这很容易”;;
--(棘手)
echo“这是一个棘手的问题”
(回声“多行”)
附和“声明”
;;
-(帮助)呼应“heeelpme”;;
-q |——安静);;
*)呼应“未知选项”;;
以撒
案例结束=$(“$LINENO”-2))#存储结束的行号
#-在$case\u start和$case\u end之间划线
#-用空格替换换行符
#-用换行符替换“;”
#->现在每个案例陈述都应该在自己的行上
#-然后过滤掉案例:删除第一个“)”之后的所有内容,包括“)”和修剪空白
cases_available=`sed-n“${case_start},${case_end}p“$0 | sed's/#.*/'| tr'\n''.| sed's//\n/g’| sed’s/)./;s/[:blank:][]*/'`
echo-e“案例可用:\n\n$cases\u可用”
这将打印:
cases_available:
simple_case
--tricky
-h|--help
-q|--quiet
*
可提供的案例:
简单案例
--狡猾的
-h |——救命
-q |——安静
*
这其中有一些陷阱:
- case语句中带有“;”的注释或字符串将破坏内容
- 无法处理嵌套的开关大小写语句
在“>case.sh”中回显“case”“$1”
echo“test)”>>case.sh
回声“回声”这个案子!“”>>case.sh
echo“;”>>case.sh
echo“esac”>>case.sh
chmod+x case.sh
/case.sh测试
#这个案子!
通过这种方式,您可以轻松地使用变量来构建开关/案例条件。这正是我试图避免的。我希望有一些函数
listalcases
(可以自动遍历开关的所有情况)并像这样使用:*)listalcases
。在我所知道的所有语言中都是不可能的。好吧,没有内置函数。您必须将shell脚本作为文本处理(通过将$0与调用站点信息一起传递给函数),这在bash中当然是可能的,但这并不容易……要正确地做到这一点,您必须在调用站点之前解析shell脚本。我不会在bash中这样做,我会在C中这样做。以前肯定有人这样做过,我现在找不到类似的东西……您可以在注释(pragma)中用唯一的代码标记每个开关的开始和结束,并将其传递到perl/awk脚本(以及$0)。这已经成为。。。。可行。
cases_available:
simple_case
--tricky
-h|--help
-q|--quiet
*