Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash中的局部变量:局部vs子shell_Bash_Function_Variables_Local_Subshell - Fatal编程技术网

bash中的局部变量:局部vs子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会带来开销 那么,更好的方法是什么?

据我所知,在bash函数中创建局部变量有两种方法:创建子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"