bash - if文の括弧はどのような役割を果たしますか? [コピー]

bash - if文の括弧はどのような役割を果たしますか? [コピー]

おそらくこれはbashにのみ適用されませんが、ifステートメントで括弧の役割について混乱しています。最大はい次の形式があるようです。

if [ expression ]; then
    #do stuff
fi

しかし、それがいつも私に効果があるわけではありません。たとえば、次のスクリプトがありますtest.sh

#!/bin/bash

flag=False
if ! $flag; then
    echo "No brackets: Flag is $flag"
fi
if [ ! $flag ]; then
    echo "With brackets: Flag is $flag"
fi
echo "The end."

どの印刷

$ ./test.sh
No brackets: Flag is False
The end.

したがって、括弧を使用する文は無視されるか、Falseと評価されます。なぜこれが起こるのですか?括弧は何をしますか?

二重括弧も見たことがあります。それらはどのように使用されますか?

-

編集:重複した質問があると主張する(これそしてこれ)はこの質問の小さな部分にのみ答えます。括弧で囲まれた構文が失敗する理由(私の考えでは評価されなければならないtest ! false)と括弧内の構文が成功する理由はまだ不明ですtrue(@ilkkachuがコメントで述べたように実際に失敗する必要があるようです)。

答え1

大文字と小文字を区別しないファイルシステム(macOSなど)を除くすべてのUnixでは、次の文if

if ! $flag; then
    echo "No brackets: Flag is $flag"
fi

出力を生成します

bash: False: command not found
No brackets: Flag is False

macOSでは、ファイルシステムは大文字と小文字を区別しないため、コマンドは標準False(外部)コマンドと同じであるため、このエラーは生成されません。false

どちらの場合も、テストは! $flag正確であるため(他の理由により)テキストが印刷されます。ほとんどのUnicesはコマンドを! $flag実行してFalse失敗し、失敗は無効になるためtrueです。 macOSでは、false否定を意味するfalseを返す外部ユーティリティを実行します。

2番目ifの声明は、

if [ ! $flag ]; then
    echo "With brackets: Flag is $flag"
fi

すべてのUnixで同じように動作します。 2つの引数とを使用してユーティリティを呼び出します[。これはユーティリティと同じですtest[最後のオペランドと一致する必要があります)。デフォルトでは、文字列引数の長さがゼロでない場合(長さがゼロでない場合)、真の値が返されますが、これはfalseを返すことによって無効化され実行されません。]!Falsetest!testecho

-nわかりやすくするために、テストを使用して空でない文字列をテストすることをお勧めします。

if [ -n "$flag" ]; then ...

または、-z空の文字列をテストします。

if [ -z "$flag" ]; then ...

変数拡張への参照は、$flagファイル名のワイルドカードパターンではなく単一の単語への拡張であるため、この特定のコード部分では重要ではありません。ただし、通常、変数の拡張は単語の区切りやファイル名のグロービングを防ぐために二重引用符で囲む必要があります。

[vs.の議論については、[[以下を参照してください。

関連:

答え2

正確な答えは少し複雑です。最終的に言葉はfalse命令であり、文字列(文脈によって異なる)であることを理解してください。

詳細な説明:

文字列から始めましょうA_Non_Existing_Command

str=A_Non_Existing_Command

だから(通常は変数拡張を引用してください。)

$ if $str; then echo yes; else echo no; fi
bash: A_Non_Existing_Command: command not found
no

印刷されますいいえこれは、実行されたコマンドが失敗し(存在しない)、else部分が実行されるためです。もちろん、エラーメッセージもあります(詳細は後述)。

ただし、testコマンドtestまたは[help testread inside bash)は次のことをテストします。

角かっこの間の文字列の長さはゼロではありません。

だから:

$ if [ "$str" ]; then echo yes; else echo no; fi
yes

yesを印刷します(文字列の文字数がゼロではないため(通常はバイト)。)文字列が存在しないコマンドの名前でもあることは重要ではありません。この場合、変数の値は文字列として解釈(評価)されます。

もちろん、否定的なテストはnoを出力します:

$ if [ ! "$str" ]; then echo yes; else echo no; fi
no

これはまったく同じです[ -z "$str" ]

次にstr、内容を次に変更しFalseて同じコマンドを実行します。

 $ str=false
 $ if     "$str"  ; then echo yes; else echo no; fi
 no

 $ if [   "$str" ]; then echo yes; else echo no; fi
 yes

 $ if [ ! "$str" ]; then echo yes; else echo no; fi
 no

同じ結果(エラーなし)が出た場合、str=Falseおそらく大文字と小文字を区別しないファイルシステムを持つシステムを使用しているためです(Falseを検索すると、エラーなしでfalseが検索されます)。

関連情報