おそらくこれは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を返すことによって無効化され実行されません。]
!
False
test
!
test
echo
-n
わかりやすくするために、テストを使用して空でない文字列をテストすることをお勧めします。
if [ -n "$flag" ]; then ...
または、-z
空の文字列をテストします。
if [ -z "$flag" ]; then ...
変数拡張への参照は、$flag
ファイル名のワイルドカードパターンではなく単一の単語への拡張であるため、この特定のコード部分では重要ではありません。ただし、通常、変数の拡張は単語の区切りやファイル名のグロービングを防ぐために二重引用符で囲む必要があります。
[
vs.の議論については、[[
以下を参照してください。
関連:
man test
システムとhelp test
すべてのbash
シェルで。- スペースやその他の特殊文字が原因でシェルスクリプトが停止するのはなぜですか?
答え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 test
read 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が検索されます)。