複数の戻り値を処理するためにCaseステートメントを使用する方法

複数の戻り値を処理するためにCaseステートメントを使用する方法

次の試みを確認してください。

$ 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

関連情報