testまたは[を使用して論理NOT!を含む条件式を評価するときは、感嘆符を角かっこ内に配置する必要がありますか、それとも外部に配置する必要がありますか?

testまたは[を使用して論理NOT!を含む条件式を評価するときは、感嘆符を角かっこ内に配置する必要がありますか、それとも外部に配置する必要がありますか?

bashtestまたは組み込みコマンドを使用して[論理NOTを使用して条件式を評価するときは、感嘆!符を角かっこ内に配置する必要がありますか、それとも外部に配置する必要がありますか?それはそんなに重要なのか?

これは単純なMREです。

$ var=1
$ if [ $var -gt 0 ]; then echo "evaluated to true"; else echo "evaluated to false";  fi
evaluated to true
$ if ! [ $var -gt 0 ]; then echo "evaluated to true"; else echo "evaluated to false";  fi
evaluated to false
$ if [ ! $var -gt 0 ]; then echo "evaluated to true"; else echo "evaluated to false";  fi

ベストアンサー1

! [ "$var" -gt 0 ][ ! "$var" -gt 0 ]エラーがない限り、現在のシェルとユーティリティは重要ではありません。


しかし、引用符if ! [ $var -gt 0 ]なしで書いたことに注意してください。if [ ! $var -gt 0 ]$var本当に重要

$var空または空白が含まれている場合は中断されます。たとえば、次の内容が表示されますif ! [ -gt 0 ]。テストでは[エラーメッセージが出力され、無効な終了コード2が返されます。すると反転され、!全体の条件が真になります!

$ var=
$ if ! [ $var -gt 0 ]; then echo yes; fi
bash: [: -gt: unary operator expected
yes

特定の状況では、[ ! $var -gt 0 ]偽のエラーの返却は偽のままで、分岐が実行されないため、より安全であると見なすことができます。しかし、ここで最も即時の問題は、簡単に修正できる引用符がないことです。

見積もりについては、以下をご覧ください。いつ二重引用符が必要ですか?


ただし、引用の問題とは別に、数値以外の値があると$varエラーが発生[し、条件が偽になります。したがって、入力が有効かどうかを事前にテストするか、この可能性を処理する必要があります。場合によっては、エラーが発生した場合の正しい処置は次のとおりです。取るたとえば、エラー終了が含まれている場合は分岐です。残念ながら、シェルには例外などがないため、実際にエラーを検出する良い方法はありません。エラーと誤った結果を区別するには、$?元の値を保存して参照する必要があります。

あるいは、エラー条件が適切な結果と一致するようにテストを作成することもできます。たとえば、励起テストは代わりに追加の否定を使用して書かれていますが、[ "$1" -le 0 ]誤った入力によってエラー終了が発生するという利点があります。これは!外部でのみ機能します[

$ cat foo.sh
#!/bin/bash

if ! [ "$1" -gt 0 ]; then
    echo "invalid input '$1'"
    exit 1
fi
echo "doing work on '$1'"

$ bash foo.sh
foo.sh: line 3: [: : integer expression expected
invalid input ''

変数値の変更と行列のさまざまなテスト:

   テスト\ $ n | '0' '1' 'x'     
 ------+------------------ ------            
  [“$n”-le 0] |真または偽(エラーあり)
  [! "$n"-gt 0] | true false false(エラーあり)
! [“$n”-gt 0] |真または偽    真(エラーあり)

おそらく、過去に[テストのオペランドが演算子のように見えたときに混乱を起こしたバージョンと多少関連している可能性があります。たとえば、[ ! = x ]theのようなものは!否定的に処理され、式全体を解析することはできません。!内部に入れると[問題が複雑になるのではないかと心配するかもしれませんが、実際にそのようなことが起こるかどうかはわかりません。それにもかかわらず、POSIX互換バージョンは[少なくとも。-a-o

望むより:シェル変数を文字列リテラルと比較するときに両側にプレフィックスを追加する目的は何ですか?、特にStéphaneの優れた答え(この例を使用しました[ ! = x ])。

おすすめ記事