问题描述
每隔一段时间我都会打出一个bash脚本,它让我想起了一些设置变量的方法:
key=value
env key=value
export key=value
当你在一个脚本或一个命令中时(例如,我会经常用一个Wine发射器链接一个变量来设置正确的Wine前缀),这些似乎是完全可以互换的,但肯定不能这样。
这三种方法之间的区别是什么?你能给我一个例子,说明什么时候我特别想使用每一种方法?
绝对与What is the difference between `VAR=…` and `export VAR=…`?相关,但我想知道env
如何适用于此,并且一些示例显示每个的好处也会很好:)
最佳解决办法
让我们考虑一个具体的例子。 grep
命令使用名为GREP_OPTIONS
的环境变量来设置默认选项。
现在。鉴于文件test.txt
包含以下行:
line one
line two
运行命令grep one test.txt
将返回
line one
如果使用-v
选项运行grep,它将返回non-matching行,因此输出将会是
line two
我们现在尝试设置一个环境变量的选项。
-
在没有
export
的情况下设置的环境变量不会在您要调用的命令环境中继承。GREP_OPTIONS='-v' grep one test.txt
结果:
line one
显然,选项
-v
没有传递给grep
。当您仅为要使用的shell设置变量时,您想要使用此表单,例如,在
for i in * ; do
中,您不想导出$i
。 -
但是,该变量会传递到该特定命令行的环境中,因此您可以这样做
GREP_OPTIONS='-v' grep one test.txt
这将返回预期的结果
line two
您可以使用此表单暂时更改此特定启动程序实例的环境。
-
导出变量会导致变量被继承:
export GREP_OPTIONS='-v' grep one test.txt
现在返回
line two
这是为在shell中使用随后启动的进程设置变量的最常用方式
-
这一切都是在bash中完成的。
export
是bash内建的;VAR=whatever
是bash语法。另一方面,env
本身就是一个程序。当调用env
时,会发生以下情况:-
命令
env
将作为一个新进程执行 -
env
修改环境,并 -
调用作为参数提供的命令。
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/interpreter
。 env
不需要程序的完整路径,因为它使用execvp()
函数,它像shell一样搜索PATH
变量,然后用run命令替换它自己。因此,它可以用来找出路径上的解释器(如perl或python)”sits”的位置。
这也意味着通过修改当前路径,您可以影响将调用哪个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!