web-dev-qa-db-ja.com

Bashの単純な論理演算子

私はいくつかの変数を持っています、そして、私は次の条件をチェックしたいです(言葉で書き出されて、それから私のbashスクリプトでの試みの失敗):

if varA EQUALS 1 AND ( varB EQUALS "t1" OR varB EQUALS "t2" ) then 

do something

done.

そして失敗した試みで、私は思い付きました:

if (($varA == 1)) && ( (($varB == "t1")) || (($varC == "t2")) ); 
  then
    scale=0.05
  fi
208
Amit

あなたが実際に書いたものはほとんど動作します(すべての変数が数値であれば動作します)が、それはまったく慣用的な方法ではありません。

  • (…)括弧は サブシェル を示します。それらの中にあるのは、他の多くの言語のような表現ではありません。これはコマンドのリストです(括弧の外側と同じです)。これらのコマンドは別のサブプロセスで実行されるため、括弧内で実行されるリダイレクトや割り当てなどは、括弧外では効果がありません。
    • 先頭にドル記号が付いている$(…)コマンド置換 です。括弧内にコマンドがあり、コマンドからの出力はコマンドラインの一部として使用されます(ただし、置換は二重引用符の間にありますが、それは 別の話 )です。
  • { … }ブレースは、コマンドをグループ化するという点で括弧のようなものですが、グループ化ではなく、解析のみに影響します。プログラムx=2; { x=4; }; echo $xは4を出力しますが、x=2; (x=4); echo $xは2を出力します(閉じる前に中括弧とセミコロンが必要ですが、括弧は必要ありません。これは単なる構文の癖です。)
    • 先頭にドル記号が付いている${VAR}パラメータ展開 であり、変数の値に展開され、追加の変換が行われる可能性があります。
  • ((…))二重括弧は、 算術命令 を囲みます。つまり、整数の計算であり、構文は他のプログラミング言語に似ています。この構文は、主に割り当てと条件で使用されます。
    • 同じ構文が算術式$((…))でも使用され、式の整数値に展開されます。
  • [[ … ]]二重括弧は 条件式 を囲みます。条件式の大部分は、変数が空かどうかをテストする-n $variableや、ファイルが存在するかどうかをテストする-e $fileなど、 演算子 に基づいています。文字列の等価演算子もあります:"$string1" = "$string2"(右側がパターンであることに注意してください。たとえば、[[ $foo = a* ]]は、$fooaで始まるかどうかをテストしますが、[[ $foo = "a*" ]]$fooが正確にa*)であるかどうか、およびおなじみの!&&および||演算子が否定、結合、分離、およびグループ化のための括弧かどうかをテストします。各演算子の周りにスペースが必要であることに注意してください(例:[[ "$x" = "$y" ]]、 [[ "$x"="$y" ]])、およびブラケットの内側と外側の両方のスペースまたは;などの文字(例:[[ -n $foo ]]、 [[-n $foo]])。
  • [ … ]単一括弧は、より奇妙な(ただし、より古くて移植性の高い)条件式の代替形式です。今のところ何も書かないでください。それらを含むスクリプトを見つけたら、それらについて心配し始めます。

これは、bashでテストを記述する慣用的な方法です。

if [[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]; then

他のシェルへの移植性が必要な場合は、これが道です(追加の引用符と、個々のテストを囲む括弧のセットに注意してください):

if [ "$varA" = 1 ] && { [ "$varB" = "t1" ] || [ "$varC" = "t2" ]; }; then
602
Gilles

とても近い

if [[ $varA -eq 1 ]] && [[ $varB == 't1' || $varC == 't2' ]]; 
  then 
    scale=0.05
  fi

うまくいくはずです。

それを分解する

[[ $varA -eq 1 ]] 

整数比較です。ここで、

$varB == 't1'

文字列比較です。それ以外の場合は、比較を正しくグループ化しているだけです。

二重角括弧は条件式を区切ります。そして、私は次のことが主題についての良い読み物であると思います: "(IBM)Demystify test、[、[[((、そしてif-then-else"

31
matchew

非常に移植性のあるバージョン(レガシーボーンシェルでさえも):

if [ "$varA" = 1 -a \( "$varB" = "t1" -o "$varB" = "t2" \) ]
then    do-something
fi

これは、シェルの種類にかかわらず、最大で1つのサブプロセスのみを実行するという追加の品質(プロセス '[')を持ちます。

変数に数値が含まれる場合は、 "="を "-eq"に置き換えます。

  • 3 -eq 03は真実ですが
  • 3 = 03は偽です。 (文字列比較)
6
J.P. Tosoni

これは、if-then-else文の短縮版のコードです。

( [ $a -eq 1 ] || [ $b -eq 2 ] ) && echo "ok" || echo "nok"

以下に注意してください。

  1. ||および&&オペランドは、条件(丸括弧の間)が論理オペランド(または/および)の場合

  2. ||および&&オペランドは、条件がthen/elseを意味する場合は外側にあります。

実際には、声明は言う:

(a = 1またはb = 2)の場合は "ok"、それ以外の場合は "nok"

1
tlc
if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ]
then
    echo STR is empty but should have a value.
fi
0