以下のコードを実行しようとしていますが、ifステートメントで関数を使用しようとすると、-bash: [: too many arguments
エラー。なぜそれが起こっているのですか?
前もって感謝します!
notContainsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 1; done
return 0
}
list=( "pears" "apples" "bananas" "oranges" )
blacklist=( "oranges" "apples" )
docheck=1
for fruit in "${list[@]}"
do
if [ notContainsElement "$fruit" "${blacklist[@]}" -a $docheck = 1 ]
then
echo $fruit
fi
done
if [ ... ]
を使用する場合、実際には[
ユーティリティを使用しています(test
と同じですが、最後の引数が]
である必要があります)。
[
は、関数の実行を理解できません。文字列が必要です。幸い、ここでは[
を使用する必要はありません(少なくとも関数については)。
if [ "$docheck" -eq 1 ] && notContainsElement "$fruit" "${blacklist[@]}"; then
...
fi
最初に整数もチェックしているので、$docheck
が1でない場合に関数をまったく呼び出さないようにすることにも注意してください。
これが機能するのは、if
が任意のコマンドを受け取り、そのコマンドの終了ステータスから何をするかを決定するためです。ここでは、[ ... ]
テストを関数の呼び出しと組み合わせて使用し、&&
を中間に置いて、複合コマンドを作成します。 [ ... ]
テストと関数の両方が終了ステータスとしてゼロを返し、成功を通知した場合、複合コマンドの終了ステータスはtrueになります。
スタイルノートとして、配列に要素notが含まれているかどうかではなく、要素doesが要素に含まれているかどうかをテストします。
if [ "$docheck" -eq 1 ] && ! contains "$fruit" "${blacklist[@]}"; then ...
do配列に要素(if ! notContainsElement ...
)が含まれているかどうかをテストしたい場合、関数テストでネガティブになるとロジックが台無しになります。
試す
if notContainsElement "$fruit" "${blacklist[@]}" && test "$docheck" = 1
then
-a
オプションはシェルでもtest
オプションでもありませんここで2つの部分のテストがあります
notContainsElement "$fruit" "${blacklist[@]}"
test $docheck = 1 ## or [ $docheck = 1 ]
次にif
を使用してリンクします
if cmd1 && cmd2
指摘されたように-a
はテストオプションですが、他のテストオプションでのみ使用できるため、
if [ "$a" -lt "$b" -a "$a" -lt "$c" ]
それをテストする$a
は両方より低い$b
および$c
、ただし、テストスコープ内で他のコマンドを使用することはできません。
これは一部の人々が好まないかもしれない代替案です。ブラックリスト配列を文字列に変換し、フルーツが削除された文字列が同じかどうかを確認します。文字列にスペースを埋め込むように編集されました。アップル/パイナップル問題を指摘してくれたスコットに感謝します。
badlist=" ${blacklist[@]} "
for f in "${list[@]}"
do
if [[ "${badlist/" $f "/}" == "$badlist" ]]
then
echo "$f"
fi
done
これはもっと簡単だと思いますが、多くの人が好む&&ロジックが欠けています。