Shell 脚本中的循环变量和 `unset`

Loop Variables and `unset` in Shell Script

我只是想在这里确认一下,因为我只在 dash shell 中进行了测试,但是循环变量通常会与 shell 脚本中外部作用域中的变量发生冲突吗?例如

#! /bin/sh

i='1 2 3'
a='a b c'

for i in $a; do
  echo "$i"
done

echo "$i"

这输出:

a
b
c
c

这对我来说很有意义。也就是说,这似乎表明我是对的,循环变量会发生冲突(它们与外部作用域共享相同的命名空间)。我想知道,因为如果我使用的是没有 local 命令的旧式 shell,我想确保 unset 循环我在函数中使用的变量。我读过的文章涵盖了 unset,但似乎没有涵盖这种情况。

我说得对吗?

你要避免命名空间问题..你可以分叉你的脚本并将循环放在那个分叉里..

#! /bin/sh

i='1 2 3'
a='a b c'

function_to_fork(){
  for i in $a; do
     echo "$i"
  done
}

(function_to_fork)

echo "$i"

首先:是的,在所有符合 POSIX 的 shell 中,默认情况下变量是全局的,循环没有自己的作用域。

为防止您使用的变量转义到全局上下文,请使用 local 声明将用法封装在函数中,如下所示:

i='1 2 3'
a='a b c'

yourfunc() {
  local i             # <- here, we make i function-local
  for i in $a; do     # aside: don't use unquoted expansions like this
     echo "$i"
  done
}

yourfunc
echo "$i"

...并且 $i 不再被覆盖。


local 不是 POSIX sh 规范的一部分,但它是一个广受赞誉的扩展,甚至 ash 和 dash 都提供了它。