ステートメントの動作についていくつかのテストを行いましたが、bash
if
そのステートメントが出力される理由を正確に理解しているかどうかはわかりません。
以下は、それぞれの異なる明細出力で私が考えた理由ですif
。すべての理由は正しいですか?私も答えが見つかりません。行動の一つ以下に説明します。バッシュバージョンは4.1.2です。
#!/bin/bash
set -x
# behavior 1
if [ $anything ]; then
echo 'true 1'
fi
# result is false cause $anything will be translated by bash to an empty string, and in 'test' command, EXPRESSION omitted will be false
# behavior 2
if [ '' ];then
echo 'true 2'
fi
# result is false cause in 'test' command, EXPRESSION omitted will be false
# behavior 3
if [ 0 ]; then
echo 'true 3'
fi
# result is true cause 0 is a STRING and that is same with '-n STRING', since the length of string '0' is definitely nonzero, so it is true
# behavior 4
if [ ]; then
echo 'true 4'
fi
# result is false cause in 'test' command, EXPRESSION omitted will be false
# behavior 1a
if $anything; then
echo 'true 1a'
fi
# result is true. But I don't understand why since bash will translate $anything to an empty string, shouldn't this will result in syntax error ?
# behavior 2a
if ''; then
echo 'true 2a'
fi
# syntax error cause 'list' is empty and command can not be found
# behavior 3a
if 0; then
echo 'true 3a'
fi
# syntax error cause 'list' is 0 and there is no such command as 0
# behavior 4a
if ; then
echo 'true 4a'
fi
# syntax error cause list is empty
set +x
答え1
それは事実であることが判明した。しかし、bashが$ anythingを空の文字列に変換するので、構文エラーが発生しない理由を理解できません。
閉じていますが、クッキーはありません。次のような表現があります$anything
。if ; then
bashはできないのでエラーです分析するそれ(したがって:通事論間違い)。そこにコマンドリストがあると予想して1つを取得します;
。変数拡張が行われる前に解析が行われるため、if $anything; then
よく解析されます。次はどうなりますか?$anything
拡張、フィールドセグメンテーションなどを行います。これは空のコマンドのリストを残しますが、実際はそうです。比較する:
if "$anything"; then echo foo; fi
if $anything; then echo foo; fi
"$anything";
空のコマンドリストの代わりに、空の文字列で発生するコマンドがありますif '';
。ただし、参照されていないコンテンツは"$anything"
何も拡張されません。
$anything
これには、空白文字のみが含まれているか、ファイルとIFS
一致$IFS
しない区切りのglobリストが含まれており、このオプションが設定されている場合も同様ですnullglob
。
答え2
ステートメントの角括弧は[ "$foo" ]
コマンドの略語ですtest
。つまり [ "$foo" ]
そしてtest "$foo"
同等です。
一方、単に空白または未設定の文字列を入力すると、true
終了コードが返されます。
unset foo; $foo; echo $?
0
比較:
unset foo ; test $foo ; echo $?
1