どちらに何が好きですか?
if ! [ ... ]; then
そして
if [ ! ... ]; then
実際、結果は同じです。好みの構文はありますか?前者の構文ではnotがシェル組み込みと評価され、後者の構文ではnotが組み込みと評価されますtest
。
答え1
移植性に関する考慮事項
キーワードはPOSIXですが、Bourneではなく/コマンドは!
最初から!
サポートされています。[
test
だから[ ! ... ]
。! [ ... ]
-o
それ以外の場合は、廃止された演算子と二項演算子を使用しない限り、同じでなければなりません(実装時に古い/解析バグを除外する-a
場合)。test
[
実際、Bourneシェルは次のことを行います。
if ! cmd1; then
cmd2
fi
あなたはこれをしなければなりません:
if cmd1; then
:
else
cmd2
fi
(またはを使用してくださいcmd1 || cmd2
。しかし、最終的にシャットダウン状態が変わる可能性があります)。
set -o errexit
//set -e
トラップとの対話ERR
if
fi
@mosvyが指摘したように、/ステートメントの条件付き部分に加えて、間[ ! ... ]
のもう1つの違いは、後者が! [ ... ]
falseを返し、オプションがオンになってもシェルが終了しないことです。! [ ... ]
errexit
!
errexit
パイプに適用すると、シェルはパイプの終了状態を次のように見なすため、効果はキャンセルされます。状況。failing-pipeline || cmd
にも同様に適用されるかfailing-pipeline && cmd
...
そしてそれは[ ! ... ]
コマンド!
に渡される一般的なパラメータです[
。最終的にシェルに関する限り、これは成功または失敗の終了状態を返すコマンドerrexit
です。[
$ sh -ec '[ ! a = a ]; echo here'; echo "$?"
1
$ sh -ec '! [ a = a ]; echo here'; echo "$?"
here
0
if
これは、に示されているように、while
//ステートメントの条件付き部分としてこれらのコマンドが実行される場合には適用されません。until
errexit
ERR
Kornの砲弾のような落とし穴にも同じことが当てはまります。
$ ksh -c 'trap "echo OUCH" ERR; ! [ a = a ]'
$ ksh -c 'trap "echo OUCH" ERR; [ ! a = a ]'
OUCH
実際、これは[
ほとんど常に条件として使用され、適用されない場合( //ステートメントまたは後に/が続く場合)には適用されないerrexit
ため、おそらく違いはありません。if
while
until
&&
||
答え2
[ … ]
同じtest …
、だから! [ … ]
同じ! test …
。これはコマンドの結果を否定することを意味しますtest
。この場合は!
シェルコマンドです。
info bash
たとえば、「パイプライン」セクションで次のようにします。
予約語「!」がパイプの前に来る場合、終了状態は上記の終了状態の論理的否定です。
一方[ ! … ]
、 を意味しますtest ! …
。これはテストで式を否定するという意味です。また見てください!
:man test
! EXPRESSION
EXPRESSION is false
だから別の意味を持つことができます。複雑な式がある場合、否定は式の一部でのみ機能できます。
あなたが好きなものはあなた次第です。