[英]Print out a list of all cases of a switch
好奇的問題。 是否有可能在 bash 中自動打印出某個 switch-case 的所有情況? 在某種程度上,它盡可能保持可維護性,這意味着如果添加新案例以打印出相同的案例,則不必添加更多代碼。
例如,如果案例代表命令,這將很有用。 然后,幫助功能可以打印出所有可用的命令。
沒有直接的方法可以實現這一點,但您可以使用數組來維護您的選擇:
# 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 將值解釋為 (glob-like) patterns 。
也就是說,正如chepner指出的那樣,也許您想將您的選擇定義為匹配字符串變體的模式:
在那種情況下:
在choices
數組中用引號定義模式; 例如, choices=( foo bar baz 'h*' )
在case
分支中不加引號地引用它; 例如, ${choices[3]})
bash
不允許您訪問它解析的令牌,也不保存case
字符串(也可以是 glob 表達式)。
不幸的是,這意味着您將無法以您希望的方式 DRY 代碼。
在將 Bash 4 的幾個特性組合在一起一段時間后,我得到了這個特性。
#!/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
輸出:
Your choice is not present in available options: C
Available options are: [ A B ]
此解決方案有 2 個部分:
coproc
- 創建子進程以從子外殼讀取和寫入element
,它既寫入coproc
進程的描述符並返回它的參數,這樣我們就可以在case ... esac
使用它如果處理所有選項都應該在case
之外完成,那么您可以使用 Bash 4 case
語句的;;&
功能,它強制檢查case
內的每個語句(通常 - 即;;
- 它在第一次匹配后停止)。 需要進行此檢查,以便我們稍后可以將所有選項收集到一個數組中
可能有很多理由不使用它(可以安全地存儲在描述符中而不讀取它們的數據的限制是其中之一),我歡迎所有可以使這個解決方案更好的評論。
不知道我是否正確理解了您的問題,但是您可以執行 此頁面所說的操作,將所有可用案例打印為默認選擇:
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
您可以讓腳本自行檢查:
#!/bin/bash
case_start=$(("$LINENO" + 2)) #store line number of start
case "$1" in
simple_case) echo "this is easy";;
--tricky)
echo "This is a tricky"
(echo "Multiline")
echo "Statement"
;;
-h|--help) echo "heeeelp me";;
-q|--quiet) ;;
*) echo "unknown option";;
esac
case_end=$(("$LINENO" - 2)) #store line number of end
# - take lines between $case_start and $case_end
# - replace newlines with spaces
# - replace ";;" with newlines
# -=> now every case statement should be on its own line
# - then filter out cases: delete everything after the first ")" including the ")" and trim blanks
cases_available=`sed -n "${case_start},${case_end}p" $0 | sed 's/#.*//' | tr '\n' ' ' | sed 's/;;/\n/g' | sed 's/).*//;s/[[:blank:]]*//'`
echo -e "cases_available:\n\n$cases_available"
這將打印:
cases_available: simple_case --tricky -h|--help -q|--quiet *
這有一些陷阱:
我認為最好的方法以及在 OP 方面是將 switch case 結構實際打印到一個新文件中,然后在需要時將它的源文件中的源文件。
echo "case "'"$1"'" in" > case.sh
echo " test)" >> case.sh
echo " echo "This case!"" >> case.sh
echo " ;;" >> case.sh
echo "esac" >> case.sh
chmod+x case.sh
./case.sh test
#This case!
通過這種方式,您可以輕松地使用變量來構建 switch/case 條件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.