||または、&&条件付き操作で複数のコマンドを使用しないのはなぜですか?

||または、&&条件付き操作で複数のコマンドを使用しないのはなぜですか?

これはシェル(bash、ダッシュ)プロンプトで機能します。

[ -z "" ] && echo A || echo B
A

しかし、文章を書こうとしています。POSIXシェルスクリプトは次のように始まります。

#!/bin/sh

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

readonly raw_input_string=${1}

[ -z "${raw_input_string}" ] && echo "The given argument is empty."; exit 1

なぜかわかりませんが、メッセージを受信して​​いません:

指定された引数が空です。

次のようにスクリプトを呼び出すと:

./test_empty_argument ""

なぜそんなことですか?

答え1

セリフに注意してください

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

これは以下に関連しています。

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1

;ほとんどの場合、引用符のない部分は改行で置き換えることができます。)

つまり、exit 1スクリプトに渡されたパラメーターの数に関係なく、ステートメントは常に実行されます。これは、メッセージをThe given argument is empty.印刷する機会がまったくないことを意味します。

テスト後に複数のステートメントを実行するために「段落構文」を使用するには{ ...; }if

if [ "$#" -ne 1 ]; then
    echo 'Invalid number of arguments, expected one.' >&2
    exit 1
fi

2回目のテストにも同じ問題があります。


~について

[ -z "" ] && echo A || echo B

これは与えられた例ではうまくいきますが、一般的です。

some-test && command1 || command2

会議いいえそして

if some-test; then
    command1
else
    command2
fi

代わりにもっと似ています。

if ! { some-test && command1; }; then
    command2
fi

または

if some-test && command1; then
    :
else
    command2
fi

つまり、テストまたは最初のコマンドが失敗した場合、2番目のコマンドが実行されます。つまり、実行される可能性があることを意味します。3つすべてスピーチが含まれています。

答え2

これ:

[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1

いいえ:

[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }

しかし、その逆は次のとおりです。

{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; } 
exit 1

スクリプトに渡した引数の数に関係なく、スクリプトは終了します。

答え3

より読みやすくする1つの方法は、次のdie関数(à la perl)を定義することです。

die() {
  printf >&2 '%s\n' "$@"
  exit 1
}

# then:

[ "$#" -eq 1 ] || die "Expected one argument, got $#"

[ -n "$1" ] || die "Empty argument not supported"

必要に応じて、色、プレフィックス、行番号などの追加機能を追加できます。

答え4

私はしばしばこれを空の文字列のテストだと思います。

if [ "x$foo" = "x" ]; then ...

関連情報