在Bash中的命令之前设置环境变量对管道中的第二个命令不起作用

在给定的shell中,通常我会设置一个或多个变量,然后运行命令。最近,我学习了一个概念,将变量定义前置到命令:

FOO=bar somecommand someargs

这工作…种。当你改变一个LC_*变量(它似乎会影响命令,但它的参数,例如,[a-z] char范围)或当输出输出到另一个命令时,它就不起作用了:

FOO=bar somecommand someargs | somecommand2  # somecommand2 is unaware of FOO

我也可以用FOO=bar来前置一些命令2,这是可行的,但会增加不必要的重复,而且它对依赖变量解释的参数(例如[a-z])没有帮助。

那么,在一行上做这个的好方法是什么呢?

我想的大概是:

FOO=bar (somecommand someargs | somecommand2)  # Doesn't actually work

我得到了很多很好的答案!目标是保持它是一行程序,最好不使用export。使用Bash调用的方法总体上是最好的,尽管带有export的插入版本更紧凑一些。使用重定向而不是管道的方法也很有趣。

376103 次浏览

如何导出变量,但只在子壳内?:

(export FOO=bar && somecommand someargs | somecommand2)

基思有一个点,无条件地执行命令,这样做:

(export FOO=bar; somecommand someargs | somecommand2)
FOO=bar bash -c 'somecommand someargs | somecommand2'

使用shell脚本:

#!/bin/bash
# myscript
FOO=bar
somecommand someargs | somecommand2


> ./myscript

你也可以使用eval:

FOO=bar eval 'somecommand someargs | somecommand2'

由于这个带有eval的答案似乎并不能让每个人都满意,让我澄清一些事情:当按照书面形式使用时,用单引号是完全安全的。它很好,因为它不会启动外部进程(就像接受的答案一样),也不会在额外的子shell中执行命令(就像其他答案一样)。

当我们得到一些常规视图时,给出一个能让所有人都满意的eval替代方案,并且具有这个快速eval“技巧”的所有好处(甚至更多!),可能是很好的。只需使用函数!用你所有的命令定义一个函数:

mypipe() {
somecommand someargs | somecommand2
}

然后像这样用你的环境变量执行它:

FOO=bar mypipe

使用env

例如,env FOO=BAR command。注意,当command完成执行时,环境变量将再次恢复/不变。

只是要注意shell替换的发生,也就是说,如果你想在同一个命令行上显式引用$FOO,你可能需要转义它,这样你的shell解释器就不会执行替换之前,而是运行env

$ export FOO=BAR
$ env FOO=FUBAR bash -c 'echo $FOO'
FUBAR
$ echo $FOO
BAR

一个简单的方法是使用;

例如:

ENV=prod; ansible-playbook -i inventories/$ENV --extra-vars "env=$ENV"  deauthorize_users.yml --check

command1; command2在执行command1之后依次执行command2。命令是否成功并不重要。