Bash
Bash,案例語句檢查單詞是否在數組中
我正在編寫一個腳本,它必須接受來自有限預定義列表的單詞作為參數。我也希望它完成。我將列表儲存在一個變數中以避免
complete
和之間重複case
。所以我寫了這個,完成確實有效,但case
語句沒有。為什麼?不能只用變數製作 case 語句參數嗎?declare -ar choices=('foo' 'bar' 'baz') function do_work { case "$1" in "${choices[*]}") echo 'yes!' ;; *) echo 'no!' esac } complete -W "${choices[*]}" do_work
in 中的列表
complete -W list
被解釋為一個$IFS
分隔列表,並且它是$IFS
在完成時被考慮在內的。因此,如果您有:
complete -W 'a b,c d' do_work
do_work
完成將提供a
,b,c
andd
when$IFS
包含空間和a b
andc d
when$IFS
contains,
and not space。所以它主要是被設計破壞的。它也不允許提供任意字元串作為完成。
有了這些限制,您可以做的最好的事情是假設
$IFS
永遠不會被修改(因此將始終包含空格、製表符和換行符,因此不能在完成詞中使用的字元),並執行以下操作:choices='foo bar baz' do_work() { case "$1" in (*' '*) echo 'no!';; (*) case " $choices " in (*" $1 "*) echo 'yes!';; (*) echo 'no!';; esac;; esac } complete -W "$choices" do_work
您可以添加 a
readonly IFS
以確保$IFS
永遠不會修改,但這可能會破壞事情,特別是考慮到bash
不允許您聲明已在父範圍內只讀聲明的局部變數,因此即使是這樣做的函式local IFS=,
也會破壞。至於如何檢查是否在數組的元素中找到字元串的更一般的問題,
bash
(與 zsh 相反)沒有用於該操作的運算符,但是,您可以使用循環輕鬆實現它:amongst() { local string needle="$1" shift for string do [[ $needle = "$string" ]] && return done false }
接著:
do_work { if amongst "$1" "${choices[@]}"; then echo 'yes!' else echo 'no!' fi }