bash関数での暗黙の戻り?

次のようなbash関数があるとします:

gmx(){ echo "foo"; } 

この関数は暗黙的に機能しますかechoコマンドの終了値を返すか、returnが必要ですか?

gmx(){ echo "foo"; return $? } 

bashは機能し、bash関数の最後のコマンドの終了ステータスは「返される」ステータスですが、100%確実ではありません。

回答

returnは、シェル関数または「ドットスクリプト」(ソーススクリプト)から明示的なリターンを実行します。 returnが実行されない場合、シェル関数またはドットスクリプトの最後に暗黙のリターンが行われます。

returnはパラメーターなしで実行されます。これは、最後に実行されたコマンドの終了ステータスを返すことと同じです。

これが、すべてのPOSIXでreturnが機能する方法です。シェル。

たとえば、

gmx () { echo "foo" return "$?" } 

は、

gmx () { echo "foo" return } 

これは

gmx () { echo "foo" } 

と同じです。一般に、$?まったく。実際には、将来の使用のために保存する必要がある場合にのみ必要です。たとえば、その値を複数回調査する必要がある場合(この場合、その値を変数に割り当て、その変数に対して一連のテストを実行します)。

コメント

  • returnを使用することの1つの欠点は、、サブシェルと同じプロセスでcmdを実行するいくつかのシェルが行う最適化を防ぎます。多くのシェルでは、関数の終了ステータスに' cmdが強制終了されたという情報が含まれていないことも意味します。 (ほとんどのシェルは'とにかくその情報を取得できません。)
  • pdkshとその派生物の一部(OpenBSD shまたはposh)、'があった場合は、return -- "$?"が必要です。最後のコマンドが負の数を返す関数であった可能性があります。 mksh(これもpdkshに基づく)は、関数が負の値を返すことを禁止します。
  • これは役に立ちます、私は' return xの機能がexit xとどのように異なるかを理解していません…私が知っている唯一のことはreturn xは現在のプロセスを終了しません。
  • @AlexanderMillsそうですね、'私が言ったことです:returnは、関数またはドットスクリプトから戻るために使用されます。 exitはまったく異なることをします(プロセスを終了します)。
  • そうですね、私はこれをうまく処理し始めていると思います

回答

bash(1)のマニュアルページから:

実行されると、関数の終了ステータスは、本文で最後に実行されたコマンドの終了ステータスになります。

コメント

  • そうです。当然のことながら、returnステートメントは終了ステータスにすぎませんか?
  • returnは組み込みコマンドです。ただしreturn 1exit 1などとは異なります。
  • " return [n]:関数の実行を停止し、nで指定された値を呼び出し元に返します。 nを省略した場合、戻りステータスは関数本体で最後に実行されたコマンドのステータスになります。" (ibid)したがって、returnは、指定されている場合、関数の終了ステータスを特定の値に強制します。
  • @AlexandwrMillsはい、returnおよびexitは両方とも組み込みですが、returnは関数内でのみ使用できます。 ' returnでスクリプトを終了することはできません。終了ステータスは、コマンドが返す値です。 returnは、その値を返すコマンドです。したがって、"のreturnステートメントは終了ステータスにすぎません"は正確ではありません。 1つは値、もう1つはコマンドと値です。
  • @AlexanderMills、returnは関数exitシェル全体を終了します。 'は、Cとreturnexit(n)の場合とまったく同じですが、または、Pythonではreturnsys.exit()を比較します。

回答

すでに提供されている回答に注意事項をいくつか追加します:

  • returnはシェルにとって非常に特別な意味を持っていますが、構文の観点からは、シェルに組み込まれたコマンドであり、returnステートメントです。は他の単純なコマンドと同じように解析されます。つまり、他のコマンドの引数と同様に、引用符で囲まれていない場合、$?はsplit + globの対象になります

    したがって、それを避けるために$?を引用する必要があります:

    return "$?" 
  • returnは通常、どのオプションも受け入れません(ksh93 “は通常の--help--man--author …ただし)。期待される唯一の引数(オプション)は戻りコードです。受け入れられる戻りコードの範囲は異なります。シェルからシェルへ、および0..255以外の値が

もシェルごとに異なります。詳細については、プロセス終了時のデフォルトの終了コード?を参照してください。

ほとんどのシェルは負の数を受け入れます(結局、引数はに渡されます) _exit() / exitgroup()システムコールはintであるため、値には少なくとも- 2 31 から2 31 -1であるため、シェルがその機能に対して同じ範囲を受け入れることは意味があります。

ほとんどのシェルはwaitpid()および共同。その終了ステータスを取得するAPI。ただし、その場合、$?保存されると0〜255の数値に切り捨てられます。関数を呼び出してもプロセスの生成を伴わず、waitpid()を使用して終了ステータスを取得します。これは、すべてが同じプロセスで行われるためです。多くのシェルは、waitpid()関数を呼び出すときの動作。つまり、負の値でreturnを呼び出した場合でも、$?には正の数値が含まれます。

現在、returnが負の数(ksh88、ksh93、bash、zsh、pdksh、およびmksh、yash以外の派生物)を受け入れるシェルの中には、いくつかあります( pdkshおよびyash)return -- -123と記述する必要があります。それ以外の場合、-123は3つの-1-2-3無効なオプション。

pdkshおよびそのdeとしてライバル(OpenBSD shposhなど)は、$?の負の数を保持します。 return "$?"を実行すると、$?に負の数が含まれていると失敗します(これは、最後の実行コマンドが負の数を返す関数であった場合に発生します) )。

したがって、これらのシェルではreturn -- "$?"の方が適しています。ただし、ほとんどのシェルでサポートされていますが、その構文はPOSIXではなく、実際にはmkshおよびash派生物ではサポートされていないことに注意してください。

つまり、 pdkshベースのシェルでは、関数の引数に負の数を使用できますが、使用すると、return "$@"は機能しません。他のシェルではreturn "$@"は機能するため、returnの引数として負の数(または0..255以外の数)を使用しないでください。

  • 私が知っているすべてのシェルで、関数内で実行されているサブシェル内からreturnを呼び出すと、サブシェルが終了します(指定された終了ステータスがある場合はそれまたは最後のコマンドのステータスで) run)ですが、それ以外の場合は関数からの戻りは発生しません(私にとって、POSIXがその保証を提供するかどうかは不明です。出口サブシェルの代わりに、exitを使用する必要があると主張する人もいます。内部関数)。たとえば、

    f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?" 

    は次のように出力されます:

    still inside f. Exit status: 3 f exit status: 0 
  • 回答

    はい、関数の暗黙の戻り値は、最後に実行されたの終了ステータスです。 コマンド。これは、シェルスクリプトのどの時点でも当てはまります。スクリプト実行シーケンスの任意の時点で、現在の終了ステータスは最後に実行されたコマンドの終了ステータスです。変数割り当ての一部として実行されるコマンドでさえ:var=$(exit 34)。関数との違いは、関数が関数の実行の終了時に終了ステータスを変更する可能性があることです。

    「現在の終了ステータス」を変更する別の方法は、サブシェルを開始して次のコマンドで終了することです。必要な終了ステータス:

    $ $(exit 34) $ echo "$?" 34 

    はい、終了ステータス拡張は引用符で囲む必要があります:

    $ IFS="123" $ $(exit 34) $ echo $? 4 

    (exit 34)も機能します。
    より堅牢な構成は$(return 34)であり、exitは実行中のスクリプトを「終了」する必要があると主張する人もいるかもしれません。ただし、$(return 34)どのバージョンのbashでも機能しません。したがって、移植性はありません。

    終了ステータスを設定する最も安全な方法は、関数から機能、定義、およびreturnするように設計されているため使用することです。 :

    exitstatus(){ return "${1:-"$?"}"; } 

    つまり、関数の最後にあります。何もないか、returnまたはreturn "$?"を使用するのとまったく同じです。関数の終わりは、「関数の最後のコード行」を意味する必要はありません。

    #!/bin/sh exitstatus(){ a="${1:-"$?"}"; return "$a"; } gmx(){ if [ "$1" = "one" ]; then printf "foo "; exitstatus 78 return "$?" elif [ "$1" = "two" ]; then printf "baz "; exitstatus 89 return else printf "baz "; exitstatus 90 fi } 

    出力されます:

    $ ./script foo 78 baz 89 baz 90 

    "$?"の唯一の実用的な使用法は、値を出力することです:echo "$?"または保存すること変数内にあります(これは一時的な値であり、実行されるコマンドごとに変更されるため):exitstatus=$?export EXITSTATUS="$?"

    returnコマンドでは、有効な値の範囲は通常0〜255ですが、126 + nは、特別な終了ステータスを通知するために一部のシェルで使用されるため、一般的な推奨事項は0-125を使用することです。

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です