Bash

Bash,案例語句檢查單詞是否在數組中

  • September 2, 2022

我正在編寫一個腳本,它必須接受來自有限預定義列表的單詞作為參數。我也希望它完成。我將列表儲存在一個變數中以避免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,cand dwhen$IFS包含空間和a b and c dwhen $IFScontains ,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

您可以添加 areadonly 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
}

引用自:https://unix.stackexchange.com/questions/715850