set,export和env之间的区别是什么?我应该在何时使用它们?

每隔一段时间我就会抨击一个bash脚本,它让我觉得有几种设置变量的方法:

key=value env key=value export key=value 

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

这三种方法有什么区别,你能举个例子说明我什么时候才能使用这些方法吗?

绝对与`VAR = …`和`export VAR = …`有什么区别? 但是我想知道env是如何适应这一点的,一些例子显示每个的好处也会很好:)

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

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

 line one line two 

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

 line one 

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

 line two 

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

  1. export环境变量将不会在您调用的命令的环境中inheritance。

     GREP_OPTIONS='-v' grep one test.txt 

    结果:

     line one 

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

    当您仅为要使用的shell设置变量时,您希望使用此表单,例如in for i in * ; do 你不想出口$i

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

     GREP_OPTIONS='-v' grep one test.txt 

    这将返回预期的

     line two 

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

  3. 导出变量会导致变量被inheritance:

     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()函数,就像shell一样搜索PATH变量,然后通过命令运行替换它自己。 因此,它可以用于找出解释器(如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!