優先

優先

bash には違いがありますか、それともステートメントの否定の推奨される使用法がありますか?

if ! [[ -z "${var}" ]]; then
  do_something
fi

if [[ ! -z "${var}" ]]; then
  do_something
fi

答え1

! [[ expression ]]

テスト全体がfalseを返す場合、これはtrueになります。

[[ ! expression ]]

個々の式が false を返す場合、これは true になります。


テストは複合式になる可能性があるため、大きく異なる可能性があります。例:

$ [[ ! 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
yes
$ ! [[ 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
no

個人的には、該当する場合はテスト構造内で否定を使用することを好みますが、意図に応じて外部でもまったく問題ありません。

答え2

A! cmdは実際にはパイプ、そして!終了コードを否定します全体パイプ。

man bash より:

パイプライン パイプラインは、制御演算子 | または |& のいずれかで区切られた 1 つ以上のコマンドのシーケンスです。パイプラインの形式は次のとおりです。

         [time [-p]] [ ! ] command [ [|||&] command2 ... ]

...
予約語 ! がパイプラインの前にある場合、そのパイプラインの終了ステータスは、上記の終了ステータスの論理否定になります。シェルは、パイプライン内のすべてのコマンドが終了するまで待機してから値を返します。

その意味では、

! [[ 2 -eq 2 ]]

!全体の終了コードの否定 ( ) です[[(すべて実行された後)。したがって、これは終了コード 0 になります。

!  [[ 2 -eq 2 && 3 -eq 4 ]]

しかし

A[[ ! ]]複合コマンド(パイプではありません)。man bash より:

複合コマンド
...
[[ 式 ]]
条件式式の評価に応じて 0 または 1 のステータスを返します。
式は、以下の条件式で説明するプライマリで構成されます。

したがって、終了コードは 1 になります。

[[ ! 2 -eq 2 && 3 -eq 4 ]]

なぜなら、それは実際には次のものと同等だからです。

[[ ( ! 2 -eq 2 ) && ( 3 -eq 4 ) ]]

これは短絡評価により、の右側は&&評価されず、実際には次のはるかに短い式と同等になります。

[[ ! 2 -eq 2 ]]

これは常に誤りである(1)。

つまり、内部では[[、! は部品表現の。

優先

!内部でを使用する方[[がはるかに一般的です (また、 により、より多くのシェルに移植可能[)。ただし、 を賢明に使用して否定の範囲を明示的に制限しないと、混乱が生じることがあります(これは、構造()内で問題になる可能性があります)。[

しかし、(bash、ksh、zsh では) の結果は! [[非常に明確に定義されており、理解しやすくなります。全体を実行し[[、結果を否定します。

どちらを使用するかは個人の好み(および理解)の問題です。

関連情報