'return 0'は 'true'と同じですか(シェル環境のソーススクリプトから)?

'return 0'は 'true'と同じですか(シェル環境のソーススクリプトから)?
  • 私はユーザーが自分のシェルにソースを提供する必要がある移植性の高いスクリプトを開発しています。そのため、POSIXスクリプトを使用する必要があります。

  • スクリプトには便利な関数がたくさんあり、そのうちの1つは呼び出し関数の状態を返すという点で特別ですtruefalse


return 0さて、私はこのような状況でそれを使用しました。しかし、より読みやすく、trueforfalsereturn 1それぞれ動作するようです。

問題はこれが有効かどうかです。全く同じようにそれとも違いがある場合です。ありがとうございます。

答え1

true移植可能ですが、それ自体では返されません。return true移植性がなく、安定して動作しません。

次の機能がある場合:

f() {
    true
}

そうであれば、はい、終了ステータスが0の関数から返されます。最後から落ちると、最後のコマンドの終了状態を関数の終了状態に戻します。

しかし、もちろん、true中間体自体が制御フローに影響を与えないので、これは実際の状態に戻りません。

g() {
    # silly example condition
    if [ 1 = 1 ]; then
        true
    fi
    echo something else
    false
}

ただし、明示的な戻り値を追加できます。引数がない場合、return最後のコマンドの終了状態も使用されます。:

特殊パラメータ '?'の値はn(符号なし10進整数)に設定し、nが指定されていない場合は最後に実行されたコマンドの終了状態に設定する必要があります。 nが符号なし10進整数でない場合、または255より大きい場合、結果は指定されません。

h() {
    # silly example condition
    if [ 1 = 1 ]; then
        true
        return
    fi
    echo something else
    false
}

これで、return trueいくつかのシェルで好きなように機能することができますが、最終的にはそうではないかもしれません。少なくとも zsh では引数を算術式として扱うように見えるため、return true変数の値が使用され、true設定されていない場合、デフォルトは 0 です。

% i() { return 1+1; }
% i; echo $?
2

% unset true
% j() { return true; }
% j; echo $?
0

% true=123
% j; echo $?
123

andtrueを常にandに設定し、スクリプトライブラリのユーザーがそれを混同しないことを信頼できる場合は、zshまたは標準シェルでandを使用できます。これらの名前を使用することはお勧めできませんが、同じ名前を使用することもできます。0false1return truereturn falsereturn "$true"return "$false"true_return_valuefalse_return_value

それ以外の場合は、標準シェルでtrue; returnandを使用できますが、これがandより読みやすいfalse; returnかどうかはわかりません。いずれにせよ、シェルプログラマは実際の戻り値がゼロであることに精通している必要があります。return 0return 1

答え2

true移植可能な有効なブール値ではありませんfalse

たとえば、単純なシェルスクリプト

f()
{
  return true
}

f && echo whee

別のシェルで実行している場合:

$ sh x
return: Illegal number: 'true'
$ bash x
x: line 3: return: true: numeric argument required
$ ksh93 x
whee
$ zsh x
whee
$ ksh x
x[6]: true: bad number

(最後のシェルはpdksh 5.2.14です)

しかし、return 0携帯性は良いです。

$ cat x
f()
{
  return 0
}

f && echo whee

$ sh x
whee
$ bash x
whee
$ ksh93 x
whee
$ zsh x
whee
$ ksh x
whee

0がtrueと見なされると、戻り値が表示される可能性があるため機能します&&

今私たちはだますことができます...

f()
{
  true
}

それがすることはtrueコマンドを呼び出すことです...それから、明示的な関数を持たない関数の戻りコードがreturn最後のコマンド実行の戻り値であるという事実を使用します。

だからこれは働く明示的な動作がなく、return暗黙の動作に依存するため、読みにくいです。

答え3

これはPOSIXはこれについて何と言いますか?:

  • returnユーティリティは、シェルに現在の関数またはドットスクリプトの実行を停止させる必要があります。シェルが現在関数またはドットスクリプトを実行していない場合、結果は指定されません。
  • 特殊パラメータ '?'の値はn(符号なし10進整数)に設定し、nが指定されていない場合は最後に実行されたコマンドの終了状態に設定する必要があります。 nが符号なし10進整数でない場合、または255より大きい場合、結果は指定されません。トラップジョブ内でリターンが実行されると、最後のコマンドはトラップジョブの直前に実行されたコマンドと見なされます。

だから:

  • return関数だけでなく、ソーススクリプト(ドットスクリプト)の戻り値も使用できます。

  • 0個または1個の引数を渡すことができます(オプションなし、--受け入れられない可能性があります)、しかし符号なしの10進整数(0、、、... 、、、ではなく不明で実際に移植可能ではない)でなけれ1ばならず、10進の代わりに8進として扱うことができ、実際にはzshと同じです。同じ状況shエミュレーションで)2true0x1-1+1010

  • returnパラメータなしで前のコマンドの状態を返すので、正常な{ true; return; }終了状態を返す方法になる可能性があります。これは{ false; return; }非ゼロ(失敗)終了ステータスを返しますが、どの終了ステータスが返されるかは指定されません(実際にはfalse他のものを使用する実装を見たことがないオプションが有効になっている場合(解決可能))。これがうまくいくかどうかは不明です。実際、ダッシュやmkshにはないため、移植性はありません。1falseerrexit{ false || return; }return $(true)return $(false)

  • 何かはわかりません。シェルは現在関数やドットスクリプトを実行していません。まさに。一部の人々は、サブシェルreturnが関数やドットスクリプトで実行されても、それをサブシェルで使用されると解釈します。はい関数本体(例f() (return 1):)が指定されていません。ただし、実際にはreturnこのような場合の動作は次のとおりですexit。現在、サブシェルで終了/返却しますが、囲む関数/ドットスクリプトでは終了しません。

    とにかく、関数/ドットスクリプトから返される操作は、そのサブシェルが関数/ドットスクリプトの最後のコマンドでない場合は、サブシェルの外部で実行する必要があります。サブシェルの構成はシェルによって異なることに注意してください。たとえば、

    f() {
      cmd | {
        IFS= -r read var || return
        echo whatever
        cat
      }
      echo Here
    }
    

    returnkshまたはzshの関数から返されますが、bash(このオプションが設定されていない場合)またはdash、mkshでは返されません。lastpipeこれは、すべてのパイプラインコンポーネント、さらにはサブシェルの最後の実行(POSIXを許可)であるためです。したがって、次の方法で解決する必要があります。

    f() {
      cmd | {
        IFS= -r read var || return
        echo whatever
        cat
        true
      } || return
      echo Here
    }
    

    サブシェルを強制的に使用し、その中で使用すると、POSIXと確実に互換性があり、シェル全体で一貫した動作を維持することができます(そして変数の割り当てがパイプで維持されない可能性があることexitをより明確にします)。$varread

    f() {
      cmd | (
        IFS= -r read var || exit
        echo whatever
        cat
        true
      ) || return
      echo Here
    }
    

    (これらのすべてのreturn/はexit失敗終了ステータスを返します。/に変更して特定の失敗終了ステータス値を提供readできます)exit 1return 1

  • ! returnorの動作は! return 1移植可能ではありません(forにはあまり役に立ちませんが、returnforが失敗したシャットダウン状態にループから外れる可能性がある移植可能な場合はもっと便利です)。! break

オプション設定の特別なケースが言及されていない限り(そしてその効果が何らかの形でキャンセルされない限り)、どんな状況でも、trueandfalseコマンドは含まれる関数/ドットスクリプトを返しません。この場合、失敗したコマンドに含まれ、シェルプロセスは次のようになります。終了(必ず含まれる関数/ドットスクリプトのみを含める必要はありません)、これは通常組み込まれた一般的なコマンドですが、そうではありません。errexitfalse特殊組み込み機能// と反対の制御フローreturn演算子はbreak言うまでもありません。continue

コードをより明確にするために、オプションで成功と失敗の終了状態の変数を定義できます。たとえば、次のようになります。

ok=0 true=0 success=0 yes=0 on=0
failure=1 false=1 no=1 off=1

return "$true"or return "$false"orはと同じです。 zshでは、orまたはexitで単純化できます。return $truereturn true

しかし、算術式では意味が反転されます。 Cと同様に、0は偽を意味し、他の値は真を意味します。したがって、while (( true ))Kornと同様のシェルでは、これらの変数の値は期待どおりに機能しないため、/status_ok代わりにこれらの変数の名前を変数status_failureとして指定することをお勧めします。okfailure

関連情報