再探问题
坦率地说,手册在这一点上令人困惑。在GNU Bash的手册说:
如Shell参数中所述,可以通过在其前面添加参数分配来临时扩展任何简单命令或函数的环境(请注意,这不包括内置函数)。这些赋值语句仅影响该命令看到的环境。
如果你真的解析这句话,什么它说的是环境的命令/函数进行了修改,但不适用于父进程的环境。因此,这将起作用:
$ TESTVAR=bbb env | fgrep TESTVAR
TESTVAR=bbb
因为env命令的环境在执行前已被修改。但是,这将不起作用:
$ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc
+ TESTVAR=bbb
+ echo aaa ccc
aaa ccc
由于shell何时执行参数扩展。
口译步骤
问题的另一部分是Bash为其解释器定义了以下步骤:
- 从文件(请参阅Shell脚本),从作为-c调用选项的参数提供的字符串(请参见Invoking Bash)或从用户终端读取其输入。
- 遵循“报价”中描述的报价规则,将输入分为单词和运算符。这些标记由元字符分隔。别名扩展是通过此步骤执行的(请参阅别名)。
- 将标记解析为简单命令和复合命令(请参阅Shell命令)。
- 执行各种shell扩展(请参阅Shell Expansions),将扩展的令牌分为文件名列表(请参见Filename Expansion)以及命令和参数。
- 执行任何必要的重定向(请参阅重定向),并从参数列表中删除重定向运算符及其操作数。
- 执行命令(请参阅执行命令)。
- (可选)等待命令完成并收集其退出状态(请参阅退出状态)。
这里发生的是,内建函数没有自己的执行环境,因此他们永远看不到修改后的环境。另外,简单的命令(例如/ bin / echo)确实获得了修改后的环境(这就是env示例起作用的原因),但是在步骤4中,shell扩展正在当前环境中进行。
换句话说,您没有将'aaa $ TESTVAR ccc'传递给/ bin / echo; 您正在将插值字符串(在当前环境中已扩展)传递到/ bin / echo。在这种情况下,由于当前环境没有TESTVAR,您只需将'aaa ccc'传递给命令。
概要
文档可能会更加清晰。好东西有堆栈溢出!
也可以看看
http://www.gnu.org/software/bash/manual/bashref.html#Command-Execution-Environment