限定された定義済みリストの単語をパラメーターとして受け入れる必要があるスクリプトを作成しています。またぜひ行ってください。complete
との間の重複を避けるために、リストを変数に保存します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
ベストアンサー1
のリストは区切りリストcomplete -W list
として解釈され、完成型が考慮されます。$IFS
$IFS
したがって、次のような場合:
complete -W 'a b,c d' do_work
do_work
a
スペースが含まれている場合とb,c
スペースが含まれている場合と含まれていない場合に完成機能が提供されます。d
$IFS
a b
c d
$IFS
,
だからほとんど設計上壊れました。また、任意の文字列を完成として提供することもできません。
これらの制限を適用するための最善の方法は変更されないと$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
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
}
文字列を見つけるのに適した構造は、ハッシュテーブルまたは連想配列を使用することです。
typeset -A choices=( [foo]=1 [bar]=1 [baz]=1 )
do_work() {
if [[ -n ${choices[+$1]} ]]; then
echo 'yes!'
else
echo 'no!'
fi
}
complete -W "${!choices[*]}" do_work
これは"${!choices[*]}"
連想配列のキーを$IFS
その点の最初の文字に関連付けます(設定されていますが空の場合は区切り文字は使用されません)。
Bashアソシエーション配列は空のキーを持つことができないため、空の文字列はオプションの1つにすることはできませんが、とにかくサポートされていませcomplete -W
ん。許容できる値のうち