Bashに組み込まれているreturn
の動作を理解するのに問題があります。これがサンプルスクリプトです。
#!/bin/bash
dostuff() {
date | while true; do
echo returning 0
return 0
echo really-notreached
done
echo notreached
return 3
}
dostuff
echo returncode: $?
このスクリプトの出力は次のとおりです。
returning 0
notreached
returncode: 3
ただし、date |
が4行目から削除され、出力は予想どおりです。
returning 0
returncode: 0
上で使用したreturn
ステートメントは、break
ステートメントが動作するはずだと思ったように動作しているようですが、ループがパイプの右側にある場合に限ります。なぜそうなのですか?この動作を説明するものは、bashのmanページまたはオンラインで見つかりませんでした。スクリプトは、bash4.1.5とダッシュ0.5.5でも同じように機能します。
の中に date | while ...
シナリオでは、パイプが存在するため、whileループがサブシェルで実行されます。したがって、returnステートメントはループを中断し、subshellが終了し、関数を続行します。
サブシェルが作成されないように、パイプラインを削除するコードを再構築する必要があります。
dostuff() {
# redirect from a process substitution instead of a pipeline
while true; do
echo returning 0
return 0
echo really-notreached
done < <(date)
echo notreached
return 3
}
ただし、return
は、サブシェルではなく、関数呼び出しを終了する必要があります。 exit
は、(サブ)シェルを終了することを目的としています。文書化されていないバグ/機能だと思います。
echo|return
_はエラーになります、それは正しいです-return
は関数内にある必要があります。f(){ echo|return; }
はbash/dashで受け入れられますが、return
は関数呼び出しを終了しません。return
がサブシェルを終了する場合、それは関数の外部で機能します。したがって、結論は次のとおりです。return
は関数のサブシェルを終了しますこれは奇妙です。
関数内でreturn
すると、その関数は実行を停止しますが、プログラム全体は終了しません。
関数内でexit
すると、プログラム全体が終了します。
Bashスクリプトの本体ではreturn
できません。関数またはソース・スクリプト内ではreturn
しかできません。
例えば:
#!/usr/bin/env bash
function doSomething {
echo "a"
return
echo "b" # this will not execute because it is after 'return'
}
function doSomethingElse {
echo "d"
exit 0
echo "e" # this will not execute because the program has exited
}
doSomething
echo "c"
doSomethingElse
echo "f" # this will not execute because the program exited in 'doSomethingElse'
上記のコードを実行すると、次のように出力されます。
a
c
d
重要なのは、サブシェルは別のプロセスであるということです。親シェルに「リターンのために終了します」と言う方法は実際にはありません。
親シェルが取得する唯一のものである終了ステータスには、そのようなものはありません。
Bashのこの興味深い機能をカバーするための回答を追加します。 。 。
if(またはif/while/...のような式を持つ任意の制御コマンド)の内部に戻る
単純な式とそれほど単純でない式を使用する場合は、内部に戻ります
サブシェルの説明は良いです。コントロールは現在のサブシェルから戻ります。これはbash関数かもしれません。または、サブシェルが呼び出される原因となった式を持つネストされた制御コマンドのいずれかである可能性があります。
非常に単純な式の場合(例: 「true」または「1 == 1」では、サブシェルは呼び出されません。したがって、returnは〜normal/expected〜として動作します。
あまり単純でない式の場合(例:変数が展開され、何かと比較されると、returnはbreakのように動作します。
単純な(サブシェルなし)例:
$ rtest () { if true; then echo one; return 2; echo two; fi; echo not simple; return 7; }
$ rtest
one
$ echo $?
2
$ rtest () { if [[ 1 == 1 ]] ; then echo one; return 2; echo two; fi; echo not simple; return 7; }
$ rtest
one
$ echo $?
2
$ rtest () { if [[ 1 =~ 1 ]] ; then echo one; return 2; echo two; fi; echo not simple; return 7; }
$ rtest
one
$ echo $?
2
$ rtest () { if $DO ; then echo one; return 2; echo two; else echo three; return 3; fi; echo not simple; return 7; }
$ rtest
one
$ echo $?
2
$ rtest () { if [[ $DO ]]; then echo one; return 2; echo two; else echo three; return 3; fi; echo not simple; return 7; }
$ rtest
three
$ echo $?
3
$ rtest () { if [[ $DO == 1 ]] ; then echo one; return 2; echo two; else echo three; return 3; echo four; fi; echo not simple; return 7; }
$ rtest; echo $?
one
2
$ DO=1; rtest; echo $?
one
2
$ DO=0; rtest; echo $?
three
3
式は単純ではなく、サブシェルが呼び出されると想定しているため、戻り動作はブレークのようなものです。
NOT SIMPLE(サブシェル)の例。 。 =〜内部[[]]:
$ rtest () { if [[ $DO =~ 1 ]] ; then echo one; return 2; echo two; fi; echo not simple; return 7; }
$ rtest
not simple
$ echo $?
7