次のようなbash関数があるとします。
gmx(){
echo "foo";
}
この関数は暗黙的にecho
コマンドの終了値を返しますか、それともreturnを使用する必要がありますか?
gmx(){
echo "foo";
return $?
}
私はbashの動作方法を想定しています。bash関数の最後のコマンドの終了ステータスは「返される」ものですが、100%確実ではありません。
次のようなbash関数があるとします。
gmx(){
echo "foo";
}
この関数は暗黙的にecho
コマンドの終了値を返しますか、それともreturnを使用する必要がありますか?
gmx(){
echo "foo";
return $?
}
私はbashの動作方法を想定しています。bash関数の最後のコマンドの終了ステータスは「返される」ものですが、100%確実ではありません。
回答:
return
ない、明示的なシェル関数または「ドットスクリプト」(ソースのスクリプト)からの戻りを。return
が実行されない場合、シェル関数またはドットスクリプトの最後に暗黙の戻りが行われます。
をreturn
パラメータなしで実行すると、最後に実行したコマンドの終了ステータスを返すのと同じです。
これがreturn
すべてのPOSIXシェルで機能する方法です。
例えば、
gmx () {
echo 'foo'
return "$?"
}
したがって、
gmx () {
echo 'foo'
return
}
それは同じです
gmx () {
echo 'foo'
}
一般に、使用する必要があることはほとんどありません$?
。それを将来使用するために保存する必要がある場合にのみ必要です。たとえば、その値を複数回調査する必要がある場合(その場合、その値を変数に割り当て、その変数に対して一連のテストを実行します)。
sh
やなどposh
)のいくつかではreturn -- "$?"
、最後のコマンドが負の数を返す関数である可能性がある場合に必要になることに注意してください。mksh
(これもpdkshに基づく)関数が負の値を返すことを禁止します。
return x
機能が異なるのか理解できませんexit x
...私が知っている唯一のことはreturn x
、現在のプロセスを終了しないことです。
return
は私が言ったことです:関数またはドットスクリプトから戻るために使用されます。exit
まったく異なる処理を実行します(プロセスを終了します)。
bash(1)
manページから:
実行すると、関数の終了ステータスは、本体で最後に実行されたコマンドの終了ステータスになります。
return
組み込みコマンドだと思います- などreturn 1
とは異なりますがexit 1
return
指定されている場合、関数の終了ステータスを特定の値に強制します。
return
とexit
を除いて、両方のビルトインされているreturn
関数内でのみ使用することができます。でスクリプトを終了することはできませんreturn
。終了ステータスは、コマンドが返す値です。return
その値を返すコマンドです。したがって、「returnステートメントは単に終了ステータスにすぎない」というのは、まったく正確ではありません。1つは値で、もう1つはコマンドと値です。
return
は関数から戻り、exit
シェル全体を終了します。これは、Cとreturn
vs. exit(n)
、またはreturn
vs. sys.exit()
Python とまったく同じです。
すでに提供されている回答にいくつかの注意事項を追加します。
たとえreturn
シェルに非常に特別な意味は、ビューの構文の観点から、それはシェルの組み込みコマンドですし、return文は、他の単純なコマンドのように解析されます。つまり、他のコマンドの引数と同様に、$?
引用符で囲まれていない場合は、split + globの対象になります。
したがって、それ$?
を回避するには、それを引用する必要があります。
return "$?"
return
通常、任意のオプションを(受け入れないksh93
のはいつものを受け入れ--help
、--man
、--author
...が)。期待する唯一の引数(オプション)は戻りコードです。受け入れられる戻りコードの範囲はシェルごとに異なり、0..255以外の値が適切に反映されるかどうかも$?
シェルごとに異なります。プロセス終了時のデフォルトの終了コードを参照してください。詳細については。
ほとんどのシェルは負の数を受け入れます(結局のところ、_exit()
/ exitgroup()
システムコールに渡される引数はint
なので、少なくとも-2 31から2 31までの値を含みます -1ため、シェルがその関数に対して同じ範囲を受け入れることだけが理にかなっています) 。
ほとんどのシェルはwaitpid()
andおよびcoを使用します。その場合にはしかし、その終了ステータスを取得するためのAPI、それが0と255の間の数に切り捨てます保存に$?
。関数の呼び出しにはプロセスの生成は含まれず、waitpid()
すべてのプロセスが同じプロセスで実行されるため、その終了ステータスを取得するために使用されますが、多くのシェルもwaitpid()
関数の呼び出し時の動作を模倣しています。つまりreturn
、負の値で呼び出しても$?
、正の数が含まれます。
今、これらのシェルのうち、そのがreturn
、それはのように書く必要があるいくつかの(pdkshのとヤシュ)があり、負数(ksh88では、は、ksh93は、bash、zshの、pdkshのとmksh以外誘導体、ヤシュ)を受け入れ、return -- -123
そうでない場合として-123
3としたが-1
、-2
、-3
無効なオプション。
pdkshとその派生(OpenBSD sh
やなどposh
)は負の数をに保存するため、負の数が含まれ$?
ているreturn "$?"
と実行に失敗し$?
ます(最後の実行コマンドが負の数を返す関数であった場合に発生します)。
だからreturn -- "$?"
、それらのシェルでより良いでしょう。ただし、ほとんどのシェルではサポートされていますが、その構文はPOSIXではなく、実際にはサポートされていません。mksh
ash派生物で。
つまり、まとめると、pdkshベースのシェルでは、関数の引数に負の数を使用できますが、使用すると機能しreturn "$@"
ません。他のシェルでreturn "$@"
は機能します。負の数(または0..255以外の数)をの引数として使用することは避けてくださいreturn
。
私が知っているすべてのシェルでreturn
、関数内で実行されているサブシェル内から呼び出すと、サブシェルは終了します(提供された終了ステータスがある場合、または最後のコマンドが実行された場合)、それ以外の場合は関数から戻りません(私には、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
A (exit 34)
も動作します。
より堅牢な構成が必要$(return 34)
であり、出口は実行中のスクリプトを「終了」する必要があると主張する人もいます。ただし、bash のどのバージョンでも$(return 34)
機能しません。したがって、移植性はありません。
終了ステータスを設定する最も安全な方法は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までを使用することです。
return
ことの欠点の1つは、のようf() (...; cmd; return)
に定義された関数の場合cmd
、サブシェルと同じプロセスでいくつかのシェルがを実行することによる最適化が妨げられることです。多くのシェルでは、それはまた、関数の終了ステータスが、cmd
持っているときにkillされた情報を運ばないことを意味します(ほとんどのシェルは、とにかくその情報を取得できません)。