bash中的局部变量:local vs subshel​​l

时间:2011-01-07 12:10:06

标签: bash function variables local subshell

据我所知,有两种方法可以在bash函数中创建局部变量:创建子shell或将每个变量声明为本地变量。

例如:

# using local
function foo
{
  local count
  for count in $(seq 10)
  do
    echo $count
  done
}

# using subshell
function foo
{
  (
    for count in $(seq 10)
    do
      echo $count
    done
  )
}

很明显,使用子shell的版本更易于编写,因为您不必关心将所有变量声明为本地(更不用说由getopts等工具创建/导出的(环境)变量)。但我可以想象创建一个子shell有一个开销。

那么更好的方法是什么?有什么利弊?

2 个答案:

答案 0 :(得分:9)

创建子shell涉及fork(),因此与局部变量相比肯定会有开销。虽然子弹很便宜 - 你不需要担心它们的成本 - 它们不是免费的。

如果您的脚本将被大量使用并且性能非常重要(因此您将有数百个用户同时运行它,一天多次),那么您可能会担心该子程序的性能成本-贝壳。 OTOH,如果你每月运行一次并且整个脚本运行不到10秒,你可能不会。

然而,就清晰度而言,明确并声明变量要好得多 - 它降低了脚本破坏的风险,因为有人出现并说“显然不需要这个子shell”(并且它真的不是;我想从你的函数中删除子shell。

看看Perl脚本的演变。它们起初是一个免费的变量,变量随需求而存在。它们逐渐变得更加严谨,正常的风格现在要预先解决所有变量。在某种程度上,炮弹沿着类似的路径行进 - 但不像Perl那样严格。 Awk也是一个有趣的案例研究;它的函数使用全局变量,除非它们是函数的参数,这导致函数被写入3个活动参数(比如说)和5个有效定义局部变量的非活动参数。它略显古怪,虽然它“有效”。

答案 1 :(得分:0)

现在,确保所有函数始终将所有变量声明为本地变量非常困难。

我认为这非常容易出错,并且总是喜欢使用subshel​​l-functions:

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"

这将退出