web-dev-qa-db-ja.com

Bash関数におけるreturnとexitの違い

終了コードに関して、Bash関数のreturnステートメントとexitステートメントの違いは何ですか?

367
lecodesportif

man bashからreturn [n]へ。

関数の実行を停止し、nで指定された値を呼び出し元に返します。 nが省略された場合、戻り状況は、関数本体で最後に実行されたコマンドの戻り状況です。

... exit [n]

シェルをnの状況で終了させます。 nを省略すると、終了ステータスは最後に実行されたコマンドの終了ステータスになります。シェルが終了する前にEXITのトラップが実行されます。

編集:

質問の編集によれば、終了コードに関しては、returnは終了コードとは関係ありません。終了コードは アプリケーション/スクリプト を対象としており、機能を対象としていません。そのため、この点で、スクリプトの終了コード(呼び出し元プログラムが$?シェル変数を使用して捕捉できるもの)を設定する唯一のキーワードはexitです。

編集2:

exitを参照している私の最後のステートメントは、いくつかのコメントを引き起こしています。 OPを理解するためにreturnexitを区別するために作られました、そして実際には、anyプログラム/シェルスクリプトの与えられた点では、exitは呼び出しへの終了コードでスクリプトを終了する唯一の方法です。プロセス。

シェルで実行されるすべてのコマンドはローカルの「終了コード」を生成します。それは$?変数をそのコードに設定し、if&&および他の演算子と共に使用して条件付きで他のコマンドを実行できます。

これらの終了コード(および$?変数の値)は、コマンドを実行するたびにリセットされます。

ちなみに、スクリプトによって実行された最後のコマンドの終了コードは、呼び出しプロセスから見てスクリプト自体の終了コードとして使用されます。

最後に、関数は、呼び出されると、終了コードに関してシェルコマンドとして機能します。関数の終了コード(withinthe function)はreturnを使用して設定されます。したがって、関数return 0が実行されると、関数の実行は終了し、終了コード0が返されます。

271
Diego Sevilla

returnは現在の関数をスコープ外にさせますが、exitはスクリプトを呼び出されたところで終了させます。これを説明するためのサンプルプログラムを次に示します。

#!/bin/bash

retfunc()
{
    echo "this is retfunc()"
    return 1
}

exitfunc()
{
    echo "this is exitfunc()"
    exit 1
}

retfunc
echo "We are still here"
exitfunc
echo "We will never see this"

出力

$ ./test.sh
this is retfunc()
We are still here
this is exitfunc()
263
SiegeX

2つがどのように使用されているかを説明していないため、だれかが本当に完全に質問に答えたとは思いません。 OK私たちは、exitはスクリプトが呼び出された場所で終了することを知っていると思いますし、exitまたはexit 0、exit 7などのようにステータスを割り当てることができます。これは、他のスクリプトなどによってスクリプトが呼び出された場合に、そのスクリプトを強制的に停止させる方法を決定するために使用できます。

呼び出されるとreturnは、関数の振る舞いを示すために指定された値、通常は1または0を返します。次に例を示します。

    #!/bin/bash
    isdirectory() {
      if [ -d "$1" ]
      then
        return 0
      else
        return 1
      fi
    echo "you will not see anything after the return like this text"
    }

このようにチェックしてください:

    if isdirectory $1; then echo "is directory"; else echo "not a directory"; fi

またはこのように:

    isdirectory || echo "not a directory"

この例では、テストを使用してディレクトリが見つかったかどうかを示すことができます。戻り値の後にあるものはすべて関数内で実行されないことに注意してください。シェルでは0は真ですが、偽は1で、他のプログラムとは異なります。

機能の詳細については/ http://www.linuxjournal.com/content/return-values-bash-functions

注:isdirectory関数は、説明のみを目的としています。これは実際のスクリプトでこのようなオプションを実行する方法ではありません。

45
Mike Q

関数はスクリプトの内部にあり、通常returnステートメントを使用して呼び出されたところから戻ります。外部スクリプトを呼び出すこともまったく別の問題であり、スクリプトは通常exitステートメントで終了します。

「終了コードに関するBASH関数のreturn文とexit文の違い」はほとんどありません。両方ともステータスを返し、それ自体は返しません。ゼロの状況は成功を示し、その他の状況(1から255)は失敗を示します。 returnステートメントは、呼び出された場所からスクリプトに戻ります。一方、exitステートメントは、スクリプトが見つかった場所からスクリプト全体を終了させます。

return 0  # returns to where the function was called.  $? contains 0 (success).

return 1  # returns to where the function was called.  $? contains 1 (failure).

exit 0  # exits the script completely.  $? contains 0 (success).

exit 1  # exits the script completely.  $? contains 1 (failure).

関数が単にreturnステートメントなしで終了する場合、最後に実行されたコマンドのステータスがステータスコードとして返されます(そして$?に配置されます)。

覚えておいてください、returnとexitは0から255までのステータスコードを返します。これは$?で利用可能です。ステータスコードにそれ以外のものを入れることはできません(例: "cat"を返す)。うまくいかないだろう。しかし、スクリプトはステータスコードを使用することによって、失敗のための255の異なる理由を返すことができます。

呼び出し元のスクリプトに含まれる変数を設定したり、関数内で結果をエコーし​​て呼び出し元のスクリプトでコマンド置換を使用したりできます。しかし、returnやexitの目的は、Cのようなプログラミング言語では予想されるように、値や計算結果ではなく、ステータスコードを渡すことです。

28
user2100135

.sourceを使ってスクリプトを実行することもあります。

. a.sh

a.shexitを含めると、スクリプトが終了するだけでなく、シェルセッションが終了します。

a.shreturnを含めると、単にスクリプトの処理が停止します。

20
Juraj

簡単な言葉で(主にコーディングの初心者のために)、我々は言うことができます、

`return` : exits the function,
`exit()` : exits the program(called as process while running)

あなたが観察した場合にも、これは非常に基本的ですが...、

`return` : is the keyword
`exit()` : is the function
6
Jyo the Whiff
  • exitは現在の プロセスを終了させます ;終了コードの有無にかかわらず、これはプログラム機能ではなくシステムと見なします。調達時にはexitがシェルを終了させますが、実行時には単にスクリプトをexitにします。

  • 関数からのreturnは、呼び出しの後で、戻りコードの有無にかかわらず命令に戻ります。 returnはオプションであり、関数の末尾で暗黙的に指定されています。 returnは関数内でのみ使用できます。

それを追加したいのですが、ソース化されている間に、シェルを終了させずに関数内からスクリプトをexitすることは容易ではありません。私は思う、例は 'テスト'スクリプトに優れています

#!/bin/bash
function die(){
   echo ${1:=Something terrible wrong happen}
   #... clean your trash
   exit 1
}

[ -f /whatever/ ] || die "whatever is not available"
# now we can proceed
echo "continue"

次のようにします。

user$ ./test
Whatever is not available
user$

test - そして - シェルが閉じます。

user$ . ./test
Whatever is not available

testのみが終了し、プロンプトが表示されます。

解決策は、潜在的なプロシージャを()で囲むことです。

#!/bin/bash
function die(){
   echo $(1:=Something terrible wrong happen)
   #... clean your trash
   exit 1
}

( # added        
    [ -f /whatever/ ] || die "whatever is not available"
    # now we can proceed
    echo "continue"
) # added

どちらの場合もtestのみが終了します。

5
fcm

OPの質問:BASH関数のreturn文とexit文の終了コードに関する違いは何ですか?

事実、明確化が必要です。

  • (return | exit)ステートメントは、(function | Shell)の実行を終了するためには必要ありません。 (return | exit)ステートメントがなくても、(function | Shell)はコードリストの終わりに達すると終了します。
  • (return | exit)ステートメントは、終了した(function | Shell)から値を戻す必要はありません。すべてのプロセスに組み込み変数$?があります。これは常に数値を持ちます。これは "?= 1"のように設定することはできない特別な変数ですが、特別な方法でのみ設定されます(下記参照)。 $の値(呼び出されたfunction | sub Shell)で実行される最後のコマンドの後に、(function caller | parent Shell)に返される値があります。最後に実行されたコマンドが( "return [n]" | "exit [n]")であろうと、普通の( "return"であろうが、呼び出された関数コードの最後のコマンドであろうが)。

上の箇条書きリストで、それぞれ関数&returnまたはシェル&exitに関するステートメントを取得するには、常に最初の項目または常に2番目の項目のどちらかを "(x | y)"から選択します。

明らかなことは、両者が特殊変数$の共通の用法を共有しているということです。終了後に値を上向きに渡すため。

*今、その特別な方法のために$?設定することができます:

  • 呼び出された関数が終了して呼び出し元に戻ると、$?呼び出し元では$の最終的な値と等しくなります。終了した関数で。
  • 親シェルが単一のサブシェルを暗黙的または明示的に待機しており、そのサブシェルの終了によって解放された場合、$?親シェルでは$の最終値と等しくなります。終了したサブシェル内。
  • いくつかの組み込み関数は$を変更できますか?結果によります。しかし、そうでない人もいます。
  • 組み込み関数 "return"と "exit"、その後に数値引数が続く場合$?引数を指定して実行を終了します。

それはその$に注目する価値がありますか?次のように、サブシェルでexitを呼び出すことによって値を割り当てることができます。

# (exit 259)
# echo $?
3  
2
Craig Hicks

まず第一に、returnはキーワードで、私の友人であるexitは関数です。

とは言っても、これが最も簡単な説明です。

return関数から値を返します。

exit現在のシェルを出るか放棄する。

1
Ahmad Awais