関数出力が変数に割り当てられると、スクリプトは終了しません。

関数出力が変数に割り当てられると、スクリプトは終了しません。

以下のサンプルスクリプトに関するいくつかの質問があります。

関数を呼び出し_fooてその出力を変数としてキャプチャしたいのですが、戻り状態(ORではない可能性があります$bar)を使用するか、失敗した場合(0以外の場合)スクリプトを停止しようとしています。01exit

  • このように呼び出すとin関数が機能しないのはなぜですかexit_fooif ! bar="$(_foo)")。 「normal」が呼び出されると動作します。
    • exitifステートメントを次のように変更すると(ただし出力が失われる)、スクリプトは停止します。if ! _foo ; then
    • これはスクリプトexitのように動作し、停止しません。returnif ! bar="$(_foo)" ; then
    • 割り当てと終了なしで関数を呼び出すだけで問題ありませんが、これを呼び出すわけではvar="$(func)"ありません。
  • _foo関数でintoの出力をキャプチャし$barて戻り状態を使用するより良い方法はありますか(またはステートメント0以外の場合は?)1case

どういうわけか使用しなければならないような感じがしますtrap


簡単な例は次のとおりです。

#!/usr/bin/env bash

set -e
set -u
set -o pipefail

_foo() {
    local _retval
    echo "baz" && false
    _retval=$?
    exit ${_retval}
}

echo "start"

if ! bar="$(_foo)" ; then
    echo "foo failed"
else
    echo "foo passed"
fi

echo "${bar}"
echo "end"

出力は次のとおりです。

$ ./foo.sh 
start
foo failed
baz
end

以下はいくつかの追加例です。

これで終了します。

#!/usr/bin/env bash

set -e
set -u
set -o pipefail

func() {
    echo "func"
    exit
}

var=''
func
echo "var is ${var}"
echo "did not exit"

終了しません。

#!/usr/bin/env bash

set -e
set -u
set -o pipefail

func() {
    echo "func"
    exit
}

var=''
var="$(func)"
echo "var is ${var}"
echo "did not exit"

ベストアンサー1

exit関数だけでなく、関数内でスクリプト全体を終了します(サブシェルにもかかわらず)。おとぎ話:

#!/bin/bash
f() {
   exit 3
}
f
exit 0

上記のスクリプトは終了コード3で終了します。

#!/bin/bash
f() {
   exit 3
}
(f)
exit 0

終了コード 0 で終了します。

$(command)使用中の構文はサブシェル内で実行され、サブシェルがcommand実行exitされているレベルからのみ外れることがあります。以内に

サブシェルで実行されている項目の終了コードと出力をキャプチャしたい場合は、サブシェルが開始された環境で引き続き使用できます。

#!/bin/bash
subshelloutput="$( echo "output"; exit 3 )"
returnval=$?  # captures subshell's exit code
: more stuff follows

おすすめ記事