定义带或不带导出的变量

export name=value
name=value

答案

export name=value
name=value
$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar

bash-3.2$

其他人回答说,导出使变量可用于子外壳,这是正确的,但仅是副作用。导出变量时,会将变量放入当前 shell 的环境中(即 shell 调用 putenv(3)或 setenv(3))。进程的环境跨 exec 继承,使该变量在子 shell 中可见。

编辑(从 5 年的角度来看):这是一个愚蠢的答案。 “导出” 的目的是使变量 “处于随后执行的命令的环境中”,无论这些命令是子 shell 还是子进程。天真的实现方式是将变量简单地放在 shell 的环境中,但这将使得不可能实现export -p

$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export

export NAME=value为对子流程有意义的设置和变量。

NAME=value当前 shell 进程专用的临时或循环变量的NAME=value

更详细地, export标记环境中的变量名称,该环境将在创建时复制到子流程及其子流程。不会从子流程复制任何名称或值。

  • 一个常见的错误是在等号周围放置一个空格:

    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
  • 子流程仅看到导出的变量( B ):

    $ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
    A is . B is Bob
  • 子流程中的更改不会更改主外壳:

    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
  • 创建子流程时,标记为导出的变量具有复制的值:

    $ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
    [1] 3306
    $ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash 
    Subprocess 1 has B=Bob
    Subprocess 2 has B=Banana
    [1]+  Done         echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
  • 仅导出的变量成为环境的一部分( man environ ):

    $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob

因此,现在应该像夏天的阳光一样清晰!感谢 Brain Agnew,alexp 和 William Prusell。

export将使该变量可用于从当前 shell 派生的所有 shell。

$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset

您可能已经知道,UNIX 允许进程具有一组环境变量,这些环境变量是键 / 值对,键和值都是字符串。操作系统负责为每个进程分别保留这些对。

程序可以通过以下 UNIX API 访问其环境变量:

  • char *getenv(const char *name);
  • int setenv(const char *name, const char *value, int override);
  • int unsetenv(const char *name);

进程还从父进程继承环境变量。操作系统负责在创建子进程时创建所有 “envar” 的副本。

Bash和其他 shell 一样,能够根据用户要求设置其环境变量。这就是export目的。

export是一个 Bash 命令,用于为 Bash 设置环境变量。使用此命令设置的所有变量将被此 Bash 创建的所有进程继承。

有关Bash 环境的更多信息

Bash 中的另一种变量是内部变量。由于 Bash 不仅是交互式外壳,因此实际上是脚本解释器,与其他解释器(例如 Python)一样,它能够保留自己的变量集。应该提到的是,Bash(与 Python 不同)仅支持字符串变量。

定义 Bash 变量的符号是name=value 。这些变量保留在 Bash 中,与操作系统保留的环境变量无关。

有关Shell 参数 (包括变量)的更多信息

同样值得注意的是,根据 Bash 参考手册:

Shell Parameters 中所述,可以通过在其前面添加参数分配来临时扩展任何简单命令或功能的环境。这些赋值语句仅影响该命令看到的环境。


总结一下:

  • export用于在操作系统中设置环境变量。此后,此变量将可用于当前 Bash 进程创建的所有子进程。
  • Bash 变量符号(名称 = 值)用于设置仅对当前 bash 进程可用的局部变量
  • 在另一个命令前面加上 Bash 变量表示法只会为该命令的作用域创建环境变量。
tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
VARTEST="value of VARTEST" 
#export VARTEST="value of VARTEST" 
sudo env | grep -i vartest 
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}" 
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'