次の試みを確認してください。
$ case `true` in 0) echo success ;; *) echo fail ;; esac
fail
$ if `true` ; then
> echo "success"
> else
> echo "fail"
> fi
success
これでケースの説明が失敗するのはなぜですか?私がなぜその言葉を使用しないのか疑問に思うかもしれませんif
。説明します。私のコマンドが複雑な場合は、実行したい他の戻りコードが返されることがあります。コマンドを何度も実行したくありませんが、これはできません。
my_command
res = $?
case $? in
...
esac
これはset -e
、スクリプト内で使用しているため、my_command
失敗が返されるとスクリプトが中断されるためです。
しかし、解決策があります...
set +e
my_command
res=$?
set -e
case $? in
...
esac
しかし、見苦しいので、元の質問に戻ります...なぜそのcase my_command in ... esac
バージョンのみを使用できますか?
答え1
使用できません
case $(somecommand) in ...
somecommand
コマンド置換は終了状態ではなくコマンドの出力に拡張されるため、終了状態をテストします。
標準出力では出力が生成されないため、使用すると$(true)
機能しません。true
あなたはできます
{ somecommand; err="$?"; } || true
case $err in
0) echo success ;;
*) echo fail
esac
errexit
これにより、()で実行されているスクリプトは-e
終了しません。
マニュアルからbash
(説明からset -e
):
失敗したコマンドが while キーワードまたは Until キーワードの直後のコマンド・リストの一部であるか、if または elif 予約語の後のテストの一部である場合、シェルは終了しません。最後の&&または||次のコマンドを除いて、&&または||の一部として実行されるすべてのコマンドをリストします。、最後のコマンドを除くパイプライン内のすべてのコマンド、または!に反転したコマンドの戻り値
この場合、成功または失敗の可能性のみがある場合は、実行が簡単になります。
if somecommand; then
echo success
else
echo fail
fi
答え2
文法
`command`
これは、コマンドの標準出力を元のコマンドラインに置き換えることを意味します。出力は終了状態と同じではありません。このtrue
コマンドは出力を生成しないため、コマンドは次のようになります。
case "" in
0) echo success ;;
*) echo fail ;;
esac
次のように問題を解決できます。
case `my_command; echo $?` in
...
esac
しかし、if
コマンドにバックティックは必要ありません。次のようにする必要があります。
if true
then echo successs
else echo fail
fi
答え3
それでもこれを行うことはできますが、set -e
次のことができます。
if my_command
then
echo success
else
res=$?
case $res in
…
esac
fi
編集:あなたもこれを行うことができます
res=0
my_command || res=$?
case $res in
…
esac
答え4
私は完全に同意します。 -eを無効にして再度有効にするのは醜いので、避けるべきです。
いくつかのオプション
if my_command; then
echo "my_command ran ok"
else
rc=$?
echo "my_command exited with error code $rc"
fi
またはケースパスに行きたい場合(少しハッキング的ですが、使用法ではなく機能を示す必要があります)。
# PLEASE DO NOT ACTUALLY DO THIS
case "$(my_command > /dev/null && echo 0 || echo $?)" in
0) echo yeah ;;
11) echo "bummer" ;;
*) echo meh ;;
esac
あまり醜い解決策は次のとおりです(ユースケースが必要な場合)。
my_command && rc=0 || rc=1
case "$rc" in
...
esac