Answers:
您的假设是shell变量在环境中。这是不正确的。该export
命令定义了一个完全在环境中的名称。从而:
a=1 b=2
export b
会导致当前外壳知道$a
扩展为1和$b
2,但是子进程将不知道任何事情,a
因为它不是环境的一部分(即使在当前外壳中也是如此)。
一些有用的工具:
set
:对于查看当前shell的参数很有用,可以导出或不导出set -k
:在环境中设置分配的参数。考虑f() { set -k; env; }; f a=1
set -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
,因为这是一个子进程,因此您会看到export
ing变量的效果):
#!/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 读取在那里使用它的代码时生效。