[[ expr1 || expr2 ]] と [[ expr1 ]] ||

[[ expr1 || expr2 ]] と [[ expr1 ]] ||

とのexpr12つの条件式を考慮してください。私たちはこれをいくつかの方法で書くことができます。これには2つの可能性がありますexpr2$i -eq $j$k -eq $lbash

[[ expr1 || expr2 ]]

[[ expr1 ]] || [[ expr2 ]]

私は2番目の提案が優先されるべきであるという提案をここで見ることができると確信していますが、それを裏付ける証拠を見つけることができません。

違いがないように見えるサンプルスクリプトは次のとおりです。

for i in 0 1
do
  for j in 0 1
  do
    for k in 0 1
    do
      for l in 0 1
      do
        if [[ $i -eq $j || $k -eq $l ]]; then printf "1-yes\t"; else printf "1-no\t"; fi
        if [[ $i -eq $j ]] || [[ $k -eq $l ]]; then printf "2-yes\n"; else printf "2-no\n"; fi
      done
    done
  done
done

出力は、両方の条件付き構文が同じ結果を生成することを示しています。

1-yes   2-yes
1-yes   2-yes
1-yes   2-yes
1-yes   2-yes
1-yes   2-yes
1-no    2-no
1-no    2-no
1-yes   2-yes
1-yes   2-yes
1-no    2-no
1-no    2-no
1-yes   2-yes
1-yes   2-yes
1-yes   2-yes
1-yes   2-yes
1-yes   2-yes

ある構造を他の構造よりも使用すると利点はありますか?

ボーナスポイントは同じ質問ですが、いくつかの条件で使用され一般||化されています&&。たとえば、[[ expr1 && expr2 || expr3 ]]

答え1

私の考えでは、あなたが見るアドバイスはPOSIXについてです。シェンおよび/またはkshに表示される構成(ヒントを提供したStéphane Chazelasに感謝)ではなく、コマンドtestの役割を倍増し、bash、zsh、およびその他のシェルでも使用されるコマンドです。[[[

Cのようなほとんどの言語では、句が真または偽として知られている場合、演算の観点から残りを計算する必要はありません。 TRUE の場合、論理は続きません。または偽の場合、論理に従うか従わないそしてなど。もちろん、これは次のセクションでポインタを逆参照しようとするのではなく、ポインタがNULLのときに停止することを可能にします。

しかし、シェンコンストラクタ[ expr1 -o expr2 ](bashの実装を含む)はこれを行いません。常に両側を評価し、一方が必要な場合にのみ評価します。式1評価されます。これはtest、コマンド実装との互換性のために実行できます。 sh||&&doは一般的な原則に従います。つまり、結果が変わらない場合は評価しないでください。

したがって、注目すべき違いは次のとおりです。

: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
    echo true;
fi
cat /tmp/effect

生産する:

true
or-was-evaluated

上記の各コマンドは、以前にシェルに組み込まれて使用されていたコマンドのエイリアスで置き換えることが[できます。/usr/bin/[test[

次の2つの構成は次のとおりです。

: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
    echo true;
fi
cat /tmp/effect

または

: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
    echo true;
fi
cat /tmp/effect

単に作成して空白のままにtrueしてくださいeffect||正しく動作し、[[問題も修正します。


修正する:

@StéphaneChazelasがコメントしたように、元の質問に関連するいくつかの違いを見逃しました。ここでは(少なくとも私にとっては)最も重要なこと、つまりオペレータの優先順位について言及します。

シェルは優先順位を考慮しませんが:

if true || true && false; then
    echo true
else
    echo false
fi

作成します(優先順位がないため、最初にtrue || true評価してから&& false)。

false

[[ ]]演算子は以下より内部的&&に優先します||

if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
    echo true
else
    echo false
fi

出力量(1 -eq 1 && 1 -eq 0グループ化されているので、2番目のメンバーです||):

true

少なくとも変化の多く強く打つ扱いにくい

したがって、直接シェル論理演算子と比較して[[ ]]動作が改善されました。[ ]

関連情報