如何保留函数设置的变量同时获取其返回值且不使用子shell?
问题根源分析
你遇到的问题核心在于命令替换$(foo)会启动子shell执行foo:子shell有自己独立的环境变量空间,在子shell里设置的VARIABLE完全不会传递回父shell(也就是bar所在的shell)。所以当你在bar里执行echo $VARIABLE时,这个变量在父shell中根本没被定义,自然没有输出,只有VAR拿到了子shell里foo的输出retval。
可行解决方案
下面提供两种不同场景下的解决办法:
方案一:修改foo用变量传递返回值(适合允许改动foo的情况)
如果可以调整foo的实现,我们可以让它把原本要输出的返回值存在一个专门的变量里,这样就能在当前shell执行foo,同时拿到VARIABLE和返回值:
bar() { # 直接在当前shell执行foo,不会启动子shell foo # 从foo设置的变量中获取返回值 VAR="$FOO_RETURN" echo "$VARIABLE" >&2 echo "$VAR" >&2 } foo() { VARIABLE="test" # 用变量存储原本要输出的返回值 FOO_RETURN="retval" } bar
运行后会输出:
test retval
方案二:不修改foo,用临时文件捕获输出(适合不能改动foo的情况)
如果没办法修改foo,我们可以在当前shell执行foo,把它的输出保存到临时文件,再读取文件内容到VAR,这样既能保留VARIABLE的设置,又能拿到返回值:
bar() { # 创建临时文件存储foo的输出 local temp_file=$(mktemp) # 在当前shell执行foo,输出写入临时文件 foo > "$temp_file" # 读取临时文件内容到VAR VAR=$(cat "$temp_file") # 清理临时文件 rm "$temp_file" # 输出变量值 echo "$VARIABLE" >&2 echo "$VAR" >&2 } foo() { VARIABLE="test" echo "retval" } bar
这个脚本运行后同样会输出test和retval。
额外说明
bash里的命令替换($(...))和管道操作都会启动子shell,子shell的变量修改无法影响父shell,这是这类问题的常见诱因。上面的两种方案都是绕开子shell的限制:要么让变量在当前shell被设置,要么用外部存储(临时文件)传递输出内容。
内容的提问来源于stack exchange,提问作者Some Name
相关产品推荐
相关产品推荐

