命令替换子shell中的bash变量可见性

Don*_*tas 8 shell bash

我正在阅读一本 Linux shell 脚本书,并发现以下警告:

“命令替换会创建所谓的子外壳来运行封闭的命令。子外壳是从运行脚本的外壳生成的单独子外壳。因此,您在脚本中创建的任何变量都不能用于子外壳命令”。

我尝试在当前 bash shell 的 CLI 中创建一个变量,然后进入子 shell 检查是否可以在屏幕上打印它。所以是的,我做不到,似乎是根据上面的引文。但是,我已经使用命令替换运行了以下脚本:

#!/bin/bash
var=5.5555
ans=$(echo $var)
echo $ans
Run Code Online (Sandbox Code Playgroud)

结果是:

5.5555
Run Code Online (Sandbox Code Playgroud)

据我了解,它不应该打印 var 的值,因为子外壳不应该能够“看到它”。为什么会发生?

tec*_*raf 11

该声明:

因此,您在脚本中创建的任何变量都不能用于 subshel​​l 命令。

是假的。在父 shell 中定义的变量的范围是整个脚本(包括使用命令替换创建的子 shell)。

跑步:

#!/bin/bash
var=5.5555
ans1=$(echo $var)
ans2=$(var=6; echo $var)
echo $ans1
echo $ans2
Run Code Online (Sandbox Code Playgroud)

将给出结果:

5.5555
6
Run Code Online (Sandbox Code Playgroud)

$var 由子shell解析:

  • 如果没有指定局部变量,则使用三个全局变量的值
  • 如果指定了局部变量,则使用其值

另请参见示例 21-2


Mic*_*mer 10

所引用的陈述是不正确的。在子shell运行之前变量已经被预替换也是不正确的。

您可以直接使用变量间接验证这一点:

$ x=hello
$ echo Result is $(y=x ; echo ${!y} ; echo world)
Result is hello world
Run Code Online (Sandbox Code Playgroud)

该变量x绝对可以直接用于子shell(而不是之前扩展了其值),因为${!y}名称存储的变量中读取y- 在创建子shell时不存在。


对书中段落的慈善阅读将是说“变量”不可用,因为您无法持续修改其值。您在子 shell 中进行的任何变量分配之后都无法用于父 shell,无论是创建新变量(如y)还是将替换值分配给现有变量。如果子shell分配给x,新值将在子shell内生效,但之后读取它会给出原始值:

$ x=world
$ echo $(x=hello ; echo $x)
hello
$ echo $x
world
Run Code Online (Sandbox Code Playgroud)

至少在您引用的段落中,这不是一种非常明确的表达方式。如果整本书都是这样,你也许可以找到一本更好的(或者在这里阅读问题)。