シェル:ifでパラメータで関数を使用する

シェル:ifでパラメータで関数を使用する

以下のコードを実行しようとしていますが、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

答え1

これはif [ ... ]実際に[ユーティリティを使用することです(test最後の引数と同じですが必要です])。

[関数を実行するには文字列が必要であることを理解していません。幸いなことに[、ここではまったく使用する必要はありません(少なくともこの機能の場合)。

if [ "$docheck" -eq 1 ] && notContainsElement "$fruit" "${blacklist[@]}"; then
  ...
fi

また、整数を最初にチェックして、$docheck1以外の場合は関数呼び出しを回避できます。

ifこれは、任意のコマンドを受け入れ、コマンドの終了状態に基づいて実行するアクションを決定するために機能します。ここでは[ ... ]テストと関数呼び出しを使用し、&&途中で複合コマンドを作成します。[ ... ]テストと関数の両方が終了状態に0を返すと、複合コマンドの終了状態はtrueになり、成功を示します。

スタイルを参考に、配列いいえ要素を含むが、次のような場合する要素を含む

if [ "$docheck" -eq 1 ] && ! contains "$fruit" "${blacklist[@]}"; then ...

機能テストの結果が否定的である場合、論理は混乱します。する配列に要素(if ! notContainsElement ...)が含まれているかどうかをテストしたいと思います。

答え2

努力する

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テストの範囲内で他のコマンドを使用することはできません。

答え3

これは一部の人が好きではないかもしれない代替手段です。ブラックリスト配列を文字列に変換し、果物が削除された文字列が同じであることを確認してください。文字列を空白で埋めるように編集されました。リンゴ/パイナップルの問題を指摘してくれたScottに感謝します。

badlist=" ${blacklist[@]} "
for f in "${list[@]}"
do
    if [[ "${badlist/" $f "/}" == "$badlist" ]]
    then
        echo "$f"
    fi
done

私はこれがより簡単だと思いますが、多くの人が好きな&&ロジックが欠けています。

関連情報