web-dev-qa-db-ja.com

sh ANDおよびOR 1つのコマンドで

1行のコードで3つの条件をチェックしようとしていますが、行き詰まっています。

基本的に、私は次のコードを記述する必要があります。

[〜#〜] if [〜#〜]

string1はstring2と等しくありません

[〜#〜]および[〜#〜]

string3はstring4と等しくない

[〜#〜]または[〜#〜]

bool1 = true

[〜#〜]その後[〜#〜]

「条件を満たす条件-実行中のコード...」を表示します。

コメントで要求されたように、問題をより明確にするために例を更新しました。

#!/bin/sh

string1="a"
string2="b"
string3="c"
string4="d"
bool1=true

# the easy-to-read way ....
if [ "$string1" != "$string2" ] && [ "$string3" != "$string4" ] ; then
    echo "conditions met - running code ..."
fi

if $bool1 ; then
    echo "conditions met - running code ..."
fi

# or the shorter way ...
[ "$string1" != "$string2" ] && [ "$string3" != "$string4" ] && echo "conditions met - running code ..."

$bool1 && echo "conditions met - running code ..."

上記のコードは、2回実行される可能性があります。最初の2つの条件が満たされた場合と、3番目の条件が満たされた場合です。これは私が必要とするものではありません。

この例の問題は、「echo」への2つの異なる呼び出しが含まれることです-(注:実際のコードでは、これはエコーではありませんが、アイデアはわかります)。 3つの条件チェックを1つのコマンドに組み合わせることにより、コードの重複を減らすようにしています。

頭を振って、画面で「これは[〜#〜]ではない[〜#〜]どうやってやる!」

そして、おそらくこれを重複としてマークするために待っている他の人がいるでしょう...まあ、私は見ましたが、私がこれまでの答えからこれを行う方法を理解できるかどうか私はとんでもないです読んだ。

誰かが私を啓発してくれませんか? :)

6
teracow

これは動作します:

if [ "$string1" != "$string2" ] && [ "$string3" != "$string4" ] || [ "$bool1" == true ] ; then echo "conditions met - running code ..."; fi;

または、{;}で囲んで、読みやすく、将来のメンテナンスが容易になります。

if { [ "$string1" != "$string2" ] && [ "$string3" != "$string4" ] ;} || [ "$bool1" == true ] ; then echo "conditions met - running code ..."; fi;

参照:

  1. このようなブール変数はありません。 this を参照してください。
  2. {;}、 this を参照してください。
  3. &&には 優先順位が高い より|| = (())と[[]]の場合のみ

以下は、[&]でのみ発生する&&の優先順位が高いことの証明です。

Bool1 = trueと仮定します。

[[]]:

if [[ "$bool1" == true || "$bool1" == true && "$bool1" != true ]]; then echo 7; fi #1 #print 7, due to && higher precedence than ||
if [[ "$bool1" == true ]] || { "$bool1" == true && "$bool1" != true ;}; then echo 7; fi #same like #1
if { "$bool1" == true ]] || "$bool1" == true ;} && [[ "$bool1" != true ]] ; then echo 7; fi #not same like #1

なし[[]]、

if [ "$bool1" == true ] || [ "$bool1" == true ] && [ "$bool1" != true ]; then echo 7; fi #1, no output, due to && IS NOT higher precedence than ||
if [ "$bool1" == true ] || { [ "$bool1" == true ] && [ "$bool1" != true ] ;}; then echo 7; fi #not same like #1
if { [ "$bool1" == true ] || [ "$bool1" == true ] ;} && [ "$bool1" != true ]; then echo 7; fi #same like #1
6
林果皞

条件式の最後に使用している&&は、前のコマンド(最初の引数)がゼロのステータスを返す場合に、後続のコマンド(その2番目の引数)を実行するためのものです。プログラムのコード。また、そこに置いた$bool1は独立しているため、Bashはその値を実行するコマンドまたはプログラムの名前として解釈します。あなたが達成しようとしているのは、次のようにifコマンドを使用して行われる条件式の評価のようです:-

if [ "$string1" != "$string2" ]  && [ "$string3" != "$string4" ] || [ $bool1 -ne 0 ]; then echo "conditions met - running code ..."; fi

別の方法は、組み込みの「and」、-a、および「or」、-o、演算子を使用することです:-

if [ "$string1" != "$string2" -a "$string3" != "$string4" -o $bool1 -ne 0 ]; then echo "conditions met - running code ..."; fi

ここでも、ifコマンドを使用しない別の方法があります:-

[[ "$string1" != "$string2" && "$string3" != "$string4" || $bool1 -ne 0 ]] && echo "conditions met - running code ..."

ブール値は整数として表現されるため、「等しくない」の整数式テスト-neをここで使用できます。以下は動作を示すスクリプトです:-

#!/bin/bash

string1="Hello"
string2="Hello"
string3="Hello"
string4="Hello"
bool1=1

if [ "$string1" != "$string2" ]  && [ "$string3" != "$string4" ] || [ $bool1 -ne 0 ]; then echo "conditions met - running code ..."; fi

exit 0
1
user168819