bash中的局部变量:局部vs子shell
据我所知,在bash函数中创建局部变量有两种方法:创建子shell或将每个变量声明为局部变量 例如:bash中的局部变量:局部vs子shell,bash,function,variables,local,subshell,Bash,Function,Variables,Local,Subshell,据我所知,在bash函数中创建局部变量有两种方法:创建子shell或将每个变量声明为局部变量 例如: # using local function foo { local count for count in $(seq 10) do echo $count done } 或 显然,使用子shell的版本编写起来更简单,因为您不必关心将所有变量声明为本地变量(更不用说由类似工具创建/导出的(环境)变量)。但我可以想象,创建子shell会带来开销 那么,更好的方法是什么?
# using local
function foo
{
local count
for count in $(seq 10)
do
echo $count
done
}
或
显然,使用子shell的版本编写起来更简单,因为您不必关心将所有变量声明为本地变量(更不用说由类似工具创建/导出的(环境)变量)。但我可以想象,创建子shell会带来开销
那么,更好的方法是什么?利/弊是什么?创建子shell涉及一个
fork()
,因此与局部变量相比,它肯定有开销。虽然子壳很便宜——当你需要的时候,你不必担心它们的成本——但它们不是免费的
如果您的脚本将被大量使用,并且性能真的很重要(因此您将有数百个用户同时运行它,一天多次),那么您可能会担心子shell的性能成本。OTOH,如果你一个月运行一次,脚本作为一个整体运行不到10秒,你可能不会
然而,就清晰性而言,最好是显式的并声明变量——这样可以减少脚本中断的风险,因为有人会说“这个子shell显然不需要”(而且它确实不需要;我想从函数中删除子shell)
看看Perl脚本的演变。他们一开始是免费的,变量是按需产生的。它们逐渐变得更加严格,现在的正常风格是将所有变量都预先定义。在某种程度上,shell遵循了类似的路径——但不像Perl那样严格。Awk也是一个有趣的案例研究;它的函数使用全局变量,除非它们是函数的参数,这会导致函数使用3个活动参数(例如)和5个有效定义局部变量的非活动参数编写。它有点古怪,尽管它“有效”。现在,确保所有函数始终将所有变量声明为局部变量是相当困难的 我认为这很容易出错,并且更喜欢始终使用子shell函数:
f() (
echo "we are a subshell"
)
无需声明局部变量,但也无法更改全局变量。在我看来这是好的
另一个结果是,您始终需要检查这些函数的返回/退出代码,并相应地采取行动!
这是因为您无法从子shell函数中退出脚本
f() (
echo "Trying to exit"
exit 1
)
f
echo "Did not exit"
这将不会退出您的脚本。
您需要这样做:
f() (
echo "Trying to exit"
exit 1
)
f || exit $?
echo "Did not exit"
这将退出“但我可以想象创建子shell会有开销。”,我们在1000个测试中运行
time
命令,并找出开销,我认为它很小,甚至不存在。您可以使用set-e
绕过始终检查返回/退出代码。现在,当命令失败时,Bash将退出脚本,包括子shell返回非零返回/退出代码时。
f() (
echo "Trying to exit"
exit 1
)
f || exit $?
echo "Did not exit"