我在两者之间感到困惑.
虽然$ BASH_SUBSHELL内部变量指示子shell的嵌套级别,但$ SHLVL变量在子shell中没有显示任何更改.
它究竟意味着什么?如果我在另一个shell中打开一个shell,$ SHLVL的值会递增.不是那个子壳吗?
Eta*_*ner 13
不,在此上下文中,手动运行新shell(通过/bin/sh或/bin/bash等)不是子shell.
子shell是当外壳产生一个新的shell实例自身来处理一些工作.
使用命令替换(ie $(command))是一个子shell(就像旧的反引号调用一样).
使用管道(即echo '5.1+5.3' | bc -l)为管道的每个组件创建子壳.
使用Process Substitution(ie <(command))创建一个子shell.
分组命令(即(declare a=5; echo $a))创建子shell.
在后台运行命令(即sleep 1 &)创建子shell.
可能还有其他事情,但这些是常见的情况.
测试这很容易:
$ printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n"
Outside: 0 , 1
Inside: 1 , 1
$ (printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n")
Outside: 1 , 1
Inside: 2 , 1
$ bash -c 'printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n"'
Outside: 0 , 2
Inside: 1 , 2
$ bash -c '(printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n")'
Outside: 1 , 2
Inside: 2 , 2
Run Code Online (Sandbox Code Playgroud)
你的报价来源(通常很差,通常更好的避免,ABS)甚至可以证明这一点(并且以一种相当不清楚的方式,只是"高级"指南中普遍缺乏严谨和质量的另一个例子):
Run Code Online (Sandbox Code Playgroud)echo " \$BASH_SUBSHELL outside subshell = $BASH_SUBSHELL" # 0 ( echo " \$BASH_SUBSHELL inside subshell = $BASH_SUBSHELL" ) # 1 ( ( echo " \$BASH_SUBSHELL inside nested subshell = $BASH_SUBSHELL" ) ) # 2 # ^ ^ *** nested *** ^ ^ echo echo " \$SHLVL outside subshell = $SHLVL" # 3 ( echo " \$SHLVL inside subshell = $SHLVL" ) # 3 (No change!)
$SHLVL:
Shell级别,Bash嵌套的深度.如果在命令行中$ SHLVL为1,则在脚本中它将增加到2. 此变量不受子shell的影响.
$BASH_SUBSHELL:
表示子shell级别的变量.
以下是它们将具有不同值的方式:
# In the login bash shell
echo $BASH_SUBSHELL:$SHLVL
0:1
# 1st nested child
bash
echo $BASH_SUBSHELL:$SHLVL
0:2
# 2nd nested child
bash
echo $BASH_SUBSHELL:$SHLVL
0:3
# back to 1st nested child
exit
echo $BASH_SUBSHELL:$SHLVL
0:2
# back to parent shell
exit
echo $BASH_SUBSHELL:$SHLVL
0:1
# first level sub-shell
(echo $BASH_SUBSHELL:$SHLVL)
1:1
# 2nd level sub-shell
( (echo $BASH_SUBSHELL:$SHLVL) )
2:1
# 3rd level sub-shell
( ( (echo $BASH_SUBSHELL:$SHLVL) ) )
3:1
Run Code Online (Sandbox Code Playgroud)