以下代码可在任意数量的 Linux 发行版的 bash 中运行,包括 CentOS 6.10 - 7.8 和 Ubuntu 14.04 - 18.04。
#!/bin/bash
#
# Test for continue from subshell issue...
#
echo SHELL is $SHELL
for i in $(seq 5)
do
(
echo loop $i
if [[ $i == 2 ]] ; then
echo i = $i - continue
continue
fi
if [[ $i == 4 ]] ; then
echo i = $i - exit
exit 1
fi
echo Loop $i subshell end
)
rc=$?
echo Loop $i rc $rc
done
所有这些机器上的输出是:
SHELL is /bin/bash
loop 1
Loop 1 subshell end
Loop 1 rc 0
loop 2
i = 2 - continue
Loop 2 rc 0
loop 3
Loop 3 subshell end
Loop 3 rc 0
loop 4
i = 4 - exit
Loop 4 rc 1
loop 5
Loop 5 subshell end
Loop 5 rc 0
在 Ubuntu 20.04 计算机上:
SHELL is /bin/bash
loop 1
Loop 1 subshell end
Loop 1 rc 0
loop 2
i = 2 - continue
packages/tmp/looptest: line 14: continue: only meaningful in a `for', `while',
or `until' loop
Loop 2 subshell end
Loop 2 rc 0
loop 3
Loop 3 subshell end
Loop 3 rc 0
loop 4
i = 4 - exit
Loop 4 rc 1
loop 5
Loop 5 subshell end
Loop 5 rc 0
-- 如果我将 shebang 改为:#!/bin/sh
其行为与第一个例子相同 - 除了 - 在我们的机器上,我们专门将 /bin/sh 链接到 bash:
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 9 May 12 22:04 /bin/sh -> /bin/bash
这看起来只是......很奇怪。
这种行为似乎是在最近更新到 Ubuntu 20.04 后开始的。
我意识到可以说新的行为在技术上更正确,但是使用子 shell 来隔离循环之间的变量会非常有帮助,而且这种方法到目前为止仍然有效,这一点令人担忧。
答案1
我没有安装旧的 Ubuntu 或旧的 bash,所以我无法验证这一点。但这个错误修复对我来说似乎是一个很好的解释。
a. Fixed a bug that allowed subshells to "inherit" enclosing loops -- this
is where POSIX says the subshell is not "enclosed" by the loop.
编辑:我无法解释为什么“/bin/sh -> /bin/bash”会产生影响。