2

バイナリが存在するかどうかの通常のチェック:

if hash gdate 2>/dev/null; then
    gdate "$@"
else
    date "$@"
fi

コマンドラインから実行した場合:

vagrant@vagrant-ubuntu-saucy-32:~$ hash gdate 2>/dev/null
vagrant@vagrant-ubuntu-saucy-32:~$ echo $?
1

これは、システムに gdate がないため、スクリプトを実行すると date が呼び出されることを意味します。

では、これは上記のスニペットがこのようなものであることを意味しますか?

if 1; then
  gdate "$@"
else
  date "$@"
fi

1 は bash で true と評価されると思ったので、else ではなく if ブランチを選択すべきではないでしょうか? 誰かが私のためにこのスニペットを分解できますか?

4

3 に答える 3

3

Unix システムでは、終了ステータス 0 は成功です。それ以外は失敗です。

これは、内部test操作とは無関係です。このtestコマンドも、条件が true の場合は 0 を返し、false の場合は 1 を返します (ステータスで終了します)。


コメントと回答

pfnueselは次のように尋ねました。

これは常に真実ですか?いくつかの特定のケースで、真/偽の C のような評価はありませんか?

反例を挙げてください...はい、常に正しいと思います。[ "$var" != "value" ]; echo $?または[[ $var != value ]]; echo $?同様のコマンドの組み合わせを実行して、何が得られるかを確認してください。

i=0; (( i++ )); echo $?

うーん...興味深い; それは間違いなく私を考えさせました。複雑になりますが ( から 1 を生成することに同意すると仮定すると)、これは、コマンドが慎重に論理を反転させているecho $?ことを意味すると思います。のさまざまな値のコマンドで((テストを実行すると、式が 0 に評価されると (ポストインクリメントであるため、例のように)、終了ステータスが 1 であることがわかります。これは false です。それ以外の場合、終了ステータスは 0 です。これは true です。これはandに適用されます (そして、それは次のように思います)。(($ibashkshbashksh

このスクリプトを使用して、自分自身を明確にすることができました。

for start in {-3..3}
do
    for shell in bash ksh sh
    do
        output=$($shell -c "i=$start;"' if (( i++ )); then echo $? true $i; else echo $? false $i; fi')
        printf "%-4s %4s %s %-5s %s\n" $shell "[$start]" $output
    done
done

出力:

bash [-3] 0 true  -2
ksh  [-3] 0 true  -2
sh   [-3] 0 true  -2
bash [-2] 0 true  -1
ksh  [-2] 0 true  -1
sh   [-2] 0 true  -1
bash [-1] 0 true  0
ksh  [-1] 0 true  0
sh   [-1] 0 true  0
bash  [0] 1 false 1
ksh   [0] 1 false 1
sh    [0] 1 false 1
bash  [1] 0 true  2
ksh   [1] 0 true  2
sh    [1] 0 true  2
bash  [2] 0 true  3
ksh   [2] 0 true  3
sh    [2] 0 true  3
bash  [3] 0 true  4
ksh   [3] 0 true  4
sh    [3] 0 true  4

興味深いことに、POSIXシェル構文((はコマンドとして次の可能性を認識します。

" "で始まる文字シーケンス((が、' ' で始まる場合、シェルによって算術展開として解析される場合、$" " が算術式として評価される拡張機能を実装するシェルは、" " を算術評価として導入するものとして((expression))扱うことができます。((グループ化コマンドの代わりに。適合アプリケーションは(、シェルが算術評価を実行するのを防ぐために、先頭の 2 つの ' ' 文字を空白で区切ることを保証するものとします。

于 2013-11-02T22:26:49.413 に答える
2

コードは、分析したとおりに機能します。唯一の問題はあなたの最後の声明です。bash では、true (「成功」) はゼロの終了ステータスであり、non-true (「失敗」) はゼロ以外です。http://tldp.org/LDP/abs/html/exit-status.htmlを参照

そのため、bash では、コマンドがゼロで終了した場合、条件はそれを「真の」分岐と見なします。コマンドがゼロ以外で終了した場合、条件はそれを「false」分岐として扱います。

于 2013-11-02T22:26:37.767 に答える
1

そのスニペットは1、コマンドとして実行しようとします。おそらくその名前のコマンドはないので、条件は false です。if 0 ; then ...同じことを行います (たまたま0orという名前のコマンドがある場合を除きます1)。

常に真である条件が必要な場合は、いくつかのオプションがありますが、最も単純なものは次のとおりです。

if : ; then
     ...
fi

または、必要に応じて:

if true ; then
    ...
fi
于 2013-11-02T22:27:27.850 に答える