在bash中的命令之前设置环境变量不适用于管道中的第二个命令

Setting an environment variable before a command in bash not working for second command in a pipe

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

1
FOO=bar somecommand someargs

这工作…有点。当您更改一个lc_*变量(它似乎会影响命令,但不会影响命令的参数,例如'[a-z]'char ranges),或者将输出管道传输到另一个命令时,它不起作用:

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

我也可以在somecommand2前面加上"foo=bar",这是有效的,但会增加不必要的重复,而且对于根据变量解释的参数也没有帮助(例如"a-z")。

那么,在一条线上做这件事的好方法是什么?我在考虑以下几点:

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

编辑:我有很多好答案!我们的目标是保持这一水平,最好不要使用"出口"。使用对bash的调用的方法总体上是最好的,尽管带有"export"的附加版本稍微紧凑一些。使用重定向而不是管道的方法也很有趣。


1
FOO=bar bash -c 'somecommand someargs | somecommand2'


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

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

基思有一点,要无条件地执行命令,请执行以下操作:

1
(export FOO=bar; somecommand someargs | somecommand2)


您也可以使用eval

1
FOO=bar eval 'somecommand someargs | somecommand2'

由于这个对eval的回答似乎并不能让每个人都满意,所以让我澄清一点:当用单引号书写时,它是完全安全的。它不会启动外部进程(如接受的应答),也不会在额外的子shell中执行命令(如另一个应答),这很好。

当我们有一些固定的观点时,最好给每个人提供一个可以取悦所有人的eval的替代方案,并且有所有的好处(甚至更多!)这是一个很快的"骗局"。只需使用一个函数!使用所有命令定义函数:

1
2
3
mypipe() {
    somecommand someargs | somecommand2
}

并使用这样的环境变量执行它:

1
FOO=bar mypipe


使用shell脚本怎么样?

1
2
3
4
5
6
#!/bin/bash
# myscript
FOO=bar
somecommand someargs | somecommand2

> ./myscript