Answers:
您的假设是shell变量在环境中。这是不正确的。该export命令定义了一个完全在环境中的名称。从而:
a=1 b=2
export b
会导致当前外壳知道$a扩展为1和$b2,但是子进程将不知道任何事情,a因为它不是环境的一部分(即使在当前外壳中也是如此)。
一些有用的工具:
set:对于查看当前shell的参数很有用,可以导出或不导出set -k:在环境中设置分配的参数。考虑f() { set -k; env; }; f a=1set -a:告诉shell将设置的任何名称放入环境中。就像export在每次作业前都放。对.env文件有用,如中所示set -a; . .env; set +a。export:告诉外壳程序在环境中放置一个名称。导出和分配是两个完全不同的操作。env:作为外部命令,env只能告诉您有关继承的环境的信息,因此,对于进行健全性检查很有用。env -i:对于启动子流程之前清除环境很有用。替代export:
name=val command #在命令导出之前将该命令导出到命令中。declare/local -x name #导出名称,当您要避免将名称暴露在外部作用域时,此名称在shell函数中特别有用。set -a #导出以下所有分配。set -a
Shell变量和环境变量之间有区别。如果定义外壳变量而不使用export它,则该变量不会添加到流程环境中,因此也不会继承到其子级。
使用export该命令告诉shell将shell变量添加到环境中。您可以使用进行测试printenv(它只是将环境打印到stdout,因为这是一个子进程,因此您会看到exporting变量的效果):
#!/bin/sh
MYVAR="my cool variable"
echo "Without export:"
printenv | grep MYVAR
echo "With export:"
export MYVAR
printenv | grep MYVAR
变量一旦导出,便是环境的一部分。PATH在外壳本身中导出,而可以根据需要导出自定义变量。使用一些设置代码:
$ cat subshell.sh
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='
相比
$ cat test.sh
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh
PATH=/bin
foo=bar
PATH=/bin
foo=bar
用
$ cat test2.sh
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh
PATH=/bin
foo=bar
PATH=/bin
由于foo不是由外壳程序导出的,而且test2.sh从不导出它,因此它subshell.sh在上次运行时也不属于环境的一部分。
set -k是可以cmd ENVVAR=value代替的ENVVAR=value cmd,除非set -k在调用之前运行,否则在您的示例中无效f。而且,如今,只有很少的Shell支持它,并且仅是为了与Bourne Shell向后兼容。在Bourne(或Korn)shell中,这不适用于函数。并且由于它影响shell解析,因此必须在shell 读取在那里使用它的代码时生效。