为什么此分配对 [(测试命令)不可见?

问题描述 投票:0回答:1

我在手册中阅读有关 shell 语法的内容,并发现了以下内容

简单的命令
一个简单的命令是一系列可选变量赋值,后跟空格分隔的单词和重定向,并由控制运算符终止。

所以我决定使用以下脚本进行测试:

#!/usr/bin/bash
if myVar=hello [ "$myVar" ]; then echo "$myVar"; else echo fail "$myVar"; fi

$ ./test.sh 
fail

我不明白为什么会失败,如果我对手册的理解是正确的,这应该可行。在 ShellCheck 上尝试此脚本时,我收到以下警告:

SC2097(警告):此分配只能由分叉进程看到。

解释是:

name=World cmd "$name"
中,
name=World
作为环境的一部分传递给
cmd
(即,在 execve(2) 的
envp
参数中)。这意味着
cmd
及其子进程将看到该参数,但其他进程不会。

手册中哪里记录了此行为?没有任何地方说内联赋值(我刚刚提出这个术语)对于它们声明的命令来说是本地的。此外,这并不能解释脚本失败的原因。按照这个逻辑,[ 应该可以访问

myVar
,执行 then 块,并且脚本应该不打印任何内容。

我错过了什么?

bash
1个回答
0
投票

请参阅“简单命令扩展”部分。

当执行一个简单的命令时,shell 会执行以下操作 扩展、分配和重定向,从左到右,在 以下顺序。

  • 解析器标记为变量赋值的单词(命令名称前面的单词)和重定向将被保存 后期处理。
  • 非变量赋值或重定向的单词被扩展(参见 Shell 扩展)。如果扩展后还有剩余的话, 第一个单词被视为命令的名称, 剩下的词是论据。
  • 重定向按上述方式执行(请参阅重定向)。
  • 每个变量赋值中‘=’后面的文本经过波形符扩展、参数扩展、命令替换、算术运算 扩展,并在分配给变量之前删除引号。

如果没有命令名称结果,则变量分配会影响 当前的 shell 环境。在这样的命令的情况下(一个 仅由赋值语句和重定向组成)、赋值 语句在重定向之前执行。否则,变量 添加到执行命令的环境中并且不影响 当前的 shell 环境。如果任何作业试图 给只读变量赋值,发生错误,并且 命令以非零状态退出。

因此,首先请注意,扩展(包括用

$myVar
的值替换
myVar
)是在执行分配之前完成的。 因此,$myVar
 被替换为 
myVarprevious
 值,该值是空的。

此外,正如我以粗体突出显示的那样,即使执行分配,也仅在执行命令的环境中进行。 因此,它对任何其他命令都不可见,例如

then

else
 子句中的命令。

© www.soinside.com 2019 - 2024. All rights reserved.