set,export和env之间有什么区别?什么时候应该使用它们?


111

每隔一段时间,我都会扑灭一个bash脚本,这让我印象深刻,这里有几种设置变量的方法:

key=value
env key=value
export key=value

当您位于脚本或单个命令中时(例如,我经常将一个变量与Wine启动器链接起来以设置正确的Wine前缀),这些似乎完全可以互换,但是肯定不是这种情况。

这三种方法有什么区别,您能举一个例子说明我何时特别想使用每种方法吗?

绝对与`VAR = ...`和`export VAR = ...`有什么区别?但我也想知道如何env适应这种情况,一些展示每种优点的示例也很不错:)


5
请注意,这export key=value是扩展语法,不应在可移植脚本(即#! /bin/sh)中使用。
西蒙·里希特

Answers:


110

让我们考虑一个具体的例子。该grep命令使用称为的环境变量GREP_OPTIONS来设置默认选项。

现在。鉴于该文件test.txt包含以下几行:

line one
line two

运行命令grep one test.txt将返回

line one

如果使用该-v选项运行grep ,它将返回不匹配的行,因此输出为

line two

现在,我们将尝试使用环境变量来设置选项。

  1. 设置export为no的环境变量将不会在您正在调用的命令的环境中继承。

    GREP_OPTIONS='-v'
    grep one test.txt

    结果:

    line one

    显然,该选项-v没有传递给grep

    当您只为要使用的shell设置变量时,例如在for i in * ; do您不想导出时,您想使用这种形式$i

  2. 但是,该变量将传递到该特定命令行的环境,因此您可以执行

    GREP_OPTIONS='-v' grep one test.txt

    这将返回预期

    line two

    您可以使用此表单临时更改启动的程序的此特定实例的环境。

  3. 导出变量会导致该变量被继承:

    export GREP_OPTIONS='-v'
    grep one test.txt

    现在返回

    line two

    这是在shell中设置变量以供随后启动的进程使用的最常见方法

  4. 这一切都是在bash中完成的。export是内置的bash;VAR=whatever是bash语法。env另一方面,它本身就是一个程序。当env被调用时,下面的事情发生:

    1. 该命令env作为新进程执行
    2. env 修改环境,以及
    3. 调用作为参数提供的命令。该env过程由command过程代替。

    例:

    env GREP_OPTIONS='-v' grep one test.txt

    此命令将启动两个新进程:(i)env和(ii)grep(实际上,第二个进程将替换第一个进程)。从grep流程的角度来看,结果与运行完全相同

    GREP_OPTIONS='-v' grep one test.txt

    但是,如果您不熟悉bash或不想启动另一个shell(例如,当您使用exec()函数系列而不是system()调用时),则可以使用此惯用法。

关于的附加说明 #!/usr/bin/env

这也是为什么使用成语#!/usr/bin/env interpreter而不是的原因#!/usr/bin/interpreterenv不需要程序的完整路径,因为它使用的execvp()功能PATH就像shell一样搜索变量,然后 由运行命令替换它。因此,它可以用来找出解释器(如perl或python)在路径上的“位置”。

这也意味着通过修改当前路径,您可以影响将调用哪个python变体。这使得以下成为可能:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

而不是启动Calibre,将导致

I am an evil interpreter!

为什么GREP_OPTIONS ='-v'grep one test.txt有效?我以为它需要在'-v'之后加一个分号(但我尝试过,并且确实起作用了。)
Joe

2
因为使用分号,它被解释为两个单独的bash命令;第一个设置变量(不导出变量),第二个以不导出变量的环境开始。但是,如果没有分号,这是一个命令(grep),其后是设置本地环境。
1

但是,所有变量来自何处env?我的意思是,当您打开一个新的外壳程序时,您总是会有一些变量。所以某些程序一定已经export编辑过这些,对吗?
2014年

1
@Pithikos环境变量是通过“采购环境”设置的。默认情况下,bash将获取系统范围内的bashrc(或profile.d或bash_profile)。然后,它为您的用户〜/ .bashrc(和/或〜/ .bash_profile)提供源。这些文件中的任何一个都可以包含bash命令以获取其他脚本的源代码,因此最终可以使环境变量来自各地。
埃里克

5
set var=blah
CMCDragonkai '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.