【问题标题】:Local variables in bash: local vs subshellbash 中的局部变量:local vs subshel​​l
【发布时间】:2011-06-05 05:58:04
【问题描述】:

据我所知,在 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
  )
}

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

那么更好的方法是什么?有什么优点/缺点?

【问题讨论】:

  • “但是我可以想象创建一个子shell有一个开销。”,在1000个测试中运行time命令并找出开销,我认为它很小甚至不存在。跨度>

标签: bash function variables local subshell


【解决方案1】:

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

我认为这很容易出错,并且更喜欢总是使用 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"

这将退出

【讨论】:

  • 您可以使用set -e 绕过始终检查返回/退出代码。 Bash 现在将在命令失败时退出您的脚本,包括当子 shell 返回非零返回/退出代码时。
【解决方案2】:

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

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

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

看看 Perl 脚本的演变。他们一开始是免费的,随需而变。它们逐渐变得更加严格,现在的正常样式是预先声明所有变量。在某种程度上,shell 遵循了类似的路径——但不如 Perl 严格。 awk 也是一个有趣的案例研究;它的函数使用全局变量,除非它们是函数的参数,这导致函数被编写为使用 3 个有效参数(例如)和 5 个有效定义局部变量的无效参数。它有点古怪,尽管它“有效”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多