以下を考慮してください。
root@debian-lap:/tmp echo "Step 1 " || echo "Failed to execute step 1" ; echo "Step 2"
Step 1
Step 2
root@debian-lap:/tmp
echo
1番目と3番目のコマンドが正常に実行されていることがわかります。
最初のコマンドが失敗した場合は、スクリプトを停止して次から停止したいと思いますexit
。
root@debian-lap:/home/fugitive echo "Step 1 " || echo "Failed to execute step 1" && exit 2 ; echo "Step 2"
Step 1
exit
fugitive@debian-lap:~$
このexit
コマンドは、最初のコマンドの終了コードがゼロであってもシェルを実行して終了します。私の質問は – なぜ?
翻訳すると、次のことを意味しません。
- エコ「1段階」
- コマンドが失敗した場合は、「ステップ1を実行できません」をエコーしてスクリプトを終了します。
- それ以外の場合は、「ステップ2」がエコーされます。
確認してください:
cmd foo1 || cmd foo2 && exit
cmd foo2 and (&&) exit
失敗時にのみ実行してはいけませんかcmd foo1
?
私は何を見逃していますか?
編集する
私が本当にやりたい2番目の例を追加します(まだダミーテストです)。
root@debian-lap:/tmp/bashtest a="$(ls)" || echo "Failed" ; echo $a
test_file # < - This is OK
root@debian-lap:
root@debian-lap:/tmp/bashtest a="$(ls)" || echo "Unable to assign the variable" && exit 2; echo $a
exit
fugitive@debian-lap:~$ # <- this is confusing part
root@debian-lap:/tmp/bashtest a="$(ls /tmpppp/notexist)" || echo "Unable to assign the variable" ; echo $a
ls: cannot access /tmpppp/notexist: No such file or directory
Unable to assign the variable # <- This is also OK
root@debian-lap:
答え1
最後に実行したコマンド(echo
)が成功したためです。コマンドをグループ化するには、次のステートメントを使用する方が明確ですif
。
if ! step 1 ; then
echo >&2 "Failed to execute step 1"
exit 2
fi
エラーメッセージをグループ化して終了することもできますが、{ ... }
読み取りは少し難しいです。しかし、これは終了状態の正確な値を維持する。
step 1 || { echo >&2 "step 1 failed with code: $?"; exit 2; }
&&
エラーメッセージで失敗しても終了したいと仮定しているので、これをセミコロンに変更しました(そしてベストプラクティスのためにこれらのエラーをstderrに出力します)。
終了状態を維持するバリアントの場合は、このセクションif
にコードを追加する必要があります。else
if step 1; then
: OK, do nothing
else
echo >&2 "step 1 failed with code: $?"
exit 2
fi
(これはキーワードなしでBourneシェルとも互換性があります!
)。
または、なぜコマンドグループがこれが好きなのか、標準理論:
AND-ORリストは、AND演算子で区切られた1つ以上のパイプシーケンスです
"&&"
。"||"
演算子
"&&"
と"||"
は同じ優先順位を持ち、左の関連性を評価する必要があります。
つまり、 like は and が最初に結合されたか somecmd || echo && exit
のように動作します。つまり、 and not です。somecmd
echo
{ somecmd || echo; } && exit
somecmd || { echo && exit; }
答え2
問題はバイナリ/論理演算子の優先順位にあると思います。つまり、「and」と「or」は同じ優先順位を持つため、次の行はecho "Step 1 " || echo "Failed to execute step 1" && exit 2 ; echo "Step 2"
本質的に次のようになります( echo "Step 1 " || echo "Failed to execute step 1" ) && exit 2 ; echo "Step 2"
。
あなたはそれを試す必要がありますecho "Step 1 " || ( echo "Failed to execute step 1" && exit 2 ) ; echo "Step 2"
。