Bri*_*new 972

export 使变量可用于子流程.

那是,

export name=value
Run Code Online (Sandbox Code Playgroud)

表示变量名称可用于从该shell进程运行的任何进程.如果您希望进程使用此变量,请使用export该shell并从该shell运行该进程.

name=value
Run Code Online (Sandbox Code Playgroud)

表示变量作用域仅限于shell,并且不可用于任何其他进程.您可以将此用于(例如)循环变量,临时变量等.

重要的是要注意,导出变量不会使父进程可用.也就是说,在生成的进程中指定和导出变量不会使其在启动它的过程中可用.

  • 具体而言,导出使变量可通过环境用于子进程. (92认同)
  • 这有一个边缘案例; `name = value command`*确实*使子变量`command`中的变量可用. (14认同)
  • 我还要补充一点,如果导出位于您"源"的文件中(如.filename),那么它也会将其导出到您的工作环境中. (13认同)
  • @rogerdpack你不能没有导出吗?cat> blah \na = hi \n.等等; echo $ a; 输出'hi'给我. (5认同)
  • 很好,即使没有导出它也能工作。所以我想在获取文件时,如果使用 export 它将反映在子进程中,如果不使用它只会影响本地 bash 环境...... (3认同)
  • 谢谢.最后有人也解释了为什么你可能不想使用导出.这是我无法理解的部分.一旦你在脚本中运行下一个程序,我一直认为变量不会存在. (2认同)
  • 它似乎有效,如果变量已经是一个导出变量,你可以在没有`export`的情况下分配它,并且变化对后台进程是可见的.(我在bash和dash脚本中使用PATH变量进行了测试.) (2认同)

alx*_*lxp 238

为了说明其他答案所说的内容:

$ 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$ 
Run Code Online (Sandbox Code Playgroud)

  • 这个`$人FOOBAR ="不管" bash`一个例子 (7认同)

Wil*_*ell 70

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

编辑(5年的观点):这是一个愚蠢的答案."导出"的目的是使变量"处于随后执行的命令的环境中",无论这些命令是子单元还是子进程.一个简单的实现是简单地将变量放在shell的环境中,但这将使其无法实现export -p.

  • 问题标记为"bash",但同样适用于任何bourne-shell变体.过于具体,并提供仅适用于"bash"的答案是一个伟大的邪恶. (13认同)
  • `bash`是shell的jQuery. (12认同)
  • 我不确定`dash`与此有什么关系.原来的海报专门询问了"bash". (7认同)
  • 请注意,这并非完全正确.在`bash`中,export确实将变量添加到当前shell的环境中,但是`dash`不是这种情况.在我看来,将变量添加到当前shell的环境是实现`export`语义的最简单方法,但该行为不是强制要求的. (5认同)
  • `export 使变量可用于子shell,这是正确的` 这是一个非常令人困惑的术语使用。子shell不需要`export`来继承变量。子流程可以。 (3认同)

小智 59

有人说,在产生子壳时没有必要以bash出口,而其他人则说完全相反.需要注意的子shell之间的区别是很重要的(那些被创建(),``,$()或回路)和子(即通过名称调用,如流程文字bash出现在你的脚本).

  • 无论其导出状态如何,子shell 可以访问父级的所有变量.
  • 进程看到导出的变量.

这两个结构中常见的是,两者都不能将变量传递回父shell.

$ 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:
Run Code Online (Sandbox Code Playgroud)

还有一个混淆源:有些人认为'分叉'子进程是那些看不到非导出变量的子进程.通常fork()后跟exec()s,这就是为什么看起来fork()是要查找的东西,而实际上它是exec().您可以先使用exec命令运行没有fork()的命令,此方法启动的进程也无法访问未导出的变量:

$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
Run Code Online (Sandbox Code Playgroud)

请注意,这次我们没有看到这一parent:行,因为我们已经用exec命令替换了父shell ,因此没有什么可以执行该命令.

  • 这些 `var=asdf bash -c 'echo $var'` 或 `var=asdf exec bash -c 'echo $var'` 怎么样?输出是“asdf”。如果将“;”放在变量定义之后,则会有所不同。该怎么解释呢?看起来“var”(没有“;”)以某种方式考虑到生成的子进程,因为原始 shell 与它无关。如果在第二行执行,`echo $var` 不会打印任何内容。但一行是 `var=asdf bash -c 'echo $var'; echo $var` 给出 `asdf\nasdf`。 (2认同)

Cha*_*iam 30

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

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

更详细地,export标记环境中的变量名称,该名称在创建时复制到子进程及其子进程.从子进程中没有复制任何名称或值.

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

    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
    
    Run Code Online (Sandbox Code Playgroud)
  • B子进程只能看到导出的变量():

    $ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
    A is . B is Bob
    
    Run Code Online (Sandbox Code Playgroud)
  • 子进程中的更改不会更改主shell:

    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
    
    Run Code Online (Sandbox Code Playgroud)
  • 标记为导出的变量具有在创建子流程时复制的值:

    $ 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
    
    Run Code Online (Sandbox Code Playgroud)
  • 只有导出的变量才会成为环境的一部分(man environ):

     $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob
    
    Run Code Online (Sandbox Code Playgroud)

那么,现在它应该像夏天的太阳一样清晰!感谢Brain Agnew,alexp和William Prusell.


Joh*_*n T 11

export 将使变量可用于从当前shell分叉的所有shell.


Bri*_*son 11

应该注意的是,您可以导出变量,然后更改该值.变量的更改值将可用于子进程.为变量设置导出后,必须执行export -n <var>删除属性的操作.

$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这正是我正在寻找的信息,因为我看到一个使用环境变量的脚本,然后使用新值“重新导出”它们,我想知道是否有必要。 (5认同)

pro*_*lgo 8

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

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

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

进程还从父进程继承环境变量.操作系统负责在创建子进程时创建所有"envars"的副本.

Bash和其他shell一样,能够根据用户请求设置其环境变量.这是export存在的.

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

更多关于Bash中的环境

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

定义Bash变量的表示法是name=value.这些变量保留在Bash中,与操作系统保留的环境变量无关.

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

另外值得注意的是,根据Bash参考手册:

任何简单命令或函数的环境都可以通过在参数赋值前添加前缀来临时扩充,如Shell参数中所述.这些赋值语句仅影响该命令所见的环境.


总结一下:

  • export用于在操作系统中设置环境变量.此变量将可用于当前Bash进程创建的所有子进程.
  • Bash变量表示法(name = value)用于设置仅适用于当前bash进程的局部变量
  • 前缀为另一个命令的Bash变量表示法仅为该命令的作用域创建环境变量.


flo*_*w2k 7

接受的答案意味着这一点,但我想作出明确到shell内建的连接:

如前所述,export将使shell和子系统都可以使用变量.如果export使用时,变量将只提供在壳,只有壳内建可以访问它.

那是,

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
Run Code Online (Sandbox Code Playgroud)


Dan*_*ter 5

UNIX 的两位创建者 Brian Kernighan 和 Rob Pike 在他们的“UNIX 编程环境”一书中解释了这一点。谷歌搜索标题,你会很容易找到一个 pdf 版本。

它们在第 3.6 节中解决了 shell 变量,并在该export节末尾重点介绍了命令的使用:

当您想要在子 shell 中访问变量的值时,应该使用 shell 的 export 命令。(您可能会想为什么无法将变量的值从子外壳导出到其父外壳)。