当函数输出分配给变量时脚本不会退出

当函数输出分配给变量时脚本不会退出

关于下面示例脚本的几个问题。

我正在调用一个函数_foo并希望将其输出捕获到一个变量中$bar,但也使用返回状态(可能不是0or 1),或者失败则停止exit脚本(当非零时)。

  • 为什么这样调用时exitin 函数不起作用? _foo( if ! bar="$(_foo)")。当调用“正常”时它会起作用。
    • exit如果我将 if 语句更改为此(但我丢失了其输出),则会停止脚本:if ! _foo ; then
    • exit行为类似于return并且不会停止脚本:if ! bar="$(_foo)" ; then
    • 仅调用一个没有赋值和退出的函数就可以了,但是像这样调用它却var="$(func)"不行。
  • _foo是否有更好的方法来捕获函数中into的输出$bar以及使用返回状态(对于0or以外的其他情况1,例如case语句?)

我有一种感觉,我可能需要以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在函数内退出整个脚本而不仅仅是函数(尽管有子 shell)。阐述:

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

上面的脚本将以退出代码 3 终止,而

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

将以退出代码 0 终止。

$(command)您使用的语法在子 shell 内运行,command并且exit只能突破到子 shell 运行的层之内

如果您想捕获在子 shell 中运行的某些内容的退出代码和输出,那么它仍然可用于启动子 shell 的环境:

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

答案2

您也可以用另一种方式来做。

_foo () 
{ 
    local _retval
    declare -n output="$1"     # $output is local (by default with declare in a func.)
                               ## and points to $1
    output="baz" && false
    _retval=$?
    echo ${_retval}            # change echo to exit
}

现在_foo这样调用:

$ _foo bar
1
$ echo "$bar"
baz

当您在函数定义中更改echo为时,将退出脚本。exitexit

相关内容