![为什么 local fn=$(...) 会掩盖 $?状态码](https://linux22.com/image/104936/%E4%B8%BA%E4%BB%80%E4%B9%88%20local%20fn%3D%24(...)%20%E4%BC%9A%E6%8E%A9%E7%9B%96%20%24%EF%BC%9F%E7%8A%B6%E6%80%81%E7%A0%81.png)
两个函数定义,唯一的区别是第一个将local
存储关键字与赋值结合在一起,而第二个将它们分开:
function foo {
local fn=$(mktemp -p /path/does/not/exist 2>/dev/null)
echo $?
}
function bar {
local fn
fn=$(mktemp -p /path/does/not/exist 2>/dev/null)
echo $?
}
foo
bar
这先是“0”,然后是“1”。我希望它先回显“1”,然后再回显“1”。看来 的值$?
是赋值给 local 的结果,而不是命令替换的结果。
为什么 bash 4.2.46(1)-release 会有这样的行为?
答案1
我认为这种行为已被明确记录,因为这是一个陷阱(特别是在使用-o errexit
! 运行 bash 脚本时),但似乎并非如此。我的手册副本说明了以下内容(about ,其行为与在函数内时的global
行为相同):local
除非遇到无效选项,尝试使用 '-f foo=bar' 定义函数,尝试为只读变量分配值,尝试在不使用复合赋值语法 [...] 的情况下为数组变量分配值,其中一个名称不是有效的 shell 变量名,尝试关闭只读变量的只读状态,尝试关闭数组变量的数组状态,或者尝试使用 -f 显示不存在的函数,否则返回状态为零。
因此,这似乎local
不是其他编程语言中所期望的关键字:当向 提供类似赋值的参数时local
,这并不限定初始化;相反,local
内置命令负责使分配发生,并且返回代码是其local
本身,而不是可能在初始化程序中运行的代码,并且该返回代码仅在上面列出的条件列表中为非零。
也许从更字面意义上回答这个问题,正如 Bishop 在评论中提到的那样,bash 维护者 Chet Ramey 曾经被问到他是否会考虑local
在分配期间发生反射失败,并回答说,本质上,分配不是
local
主要任务:
因为那不是 local 及其兄弟姐妹 [...] 所做的。这些内置函数的存在是为了分配和修改变量属性。作为附加功能,它们同时支持赋值,但重要的功能是属性设置。他们不需要知道该值是如何计算的。 [...] 由于该函数正在设置属性或值,因此退出状态应反映该操作是否成功。
值得注意的是,在zsh
shell 中也可以观察到相同的行为。
解决方案是将这两个操作分开:
local variable
variable=$( somecommand )
exit_status=$?