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

Dav*_*vid 2 bash shell-script

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

我正在调用一个函数_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"
Run Code Online (Sandbox Code Playgroud)

这是输出:

$ ./foo.sh 
start
foo failed
baz
end
Run Code Online (Sandbox Code Playgroud)

这里还有一些例子:

这将退出:

#!/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"
Run Code Online (Sandbox Code Playgroud)

这不会退出:

#!/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"
Run Code Online (Sandbox Code Playgroud)

Dop*_*oti 5

exit在函数内退出整个脚本而不仅仅是函数(尽管有子 shell)。阐述:

#!/bin/bash
f() {
   exit 3
}
f
exit 0
Run Code Online (Sandbox Code Playgroud)

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

#!/bin/bash
f() {
   exit 3
}
(f)
exit 0
Run Code Online (Sandbox Code Playgroud)

将以退出代码 0 终止。

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

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

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