在给定的 shell 中,通常我会设置一个或多个变量,然后运行命令。最近我了解了将变量定义附加到命令的概念:
FOO=bar somecommand someargs
这行得通……有点。当您更改 LC_* 变量(这似乎会影响命令,但不影响其参数,例如 '[az]' 字符范围)或因此将输出管道传输到另一个命令时,它不起作用:
FOO=bar somecommand someargs | somecommand2 # somecommand2 is unaware of FOO
我也可以在 somecommand2 前面加上“FOO=bar”,这很有效,但会增加不必要的重复,而且它对根据变量解释的参数没有帮助(例如,'[az]')。
那么,在单行上执行此操作的好方法是什么?
我正在考虑以下顺序:
FOO=bar (somecommand someargs | somecommand2) # Doesn't actually work
我得到了很多很好的答案!目标是保持单线,最好不使用“导出”。使用 Bash 调用的方法总体上是最好的,尽管带有“导出”的括号版本更紧凑一些。使用重定向而不是管道的方法也很有趣。
(T=$(date) echo $T)
将起作用
FOO=bar bash -c 'somecommand someargs | somecommand2'
如何导出变量,但只在子外壳内?:
(export FOO=bar && somecommand someargs | somecommand2)
Keith 有一个观点,要无条件地执行命令,请执行以下操作:
(export FOO=bar; somecommand someargs | somecommand2)
;
而不是 &&
; export FOO=bar
不会失败。
&&
执行左侧命令,然后仅在左侧命令成功时才执行右侧命令。 ;
无条件地执行这两个命令。 ;
的 Windows 批处理 (cmd.exe
) 等效项是 &
。
(FOO=XXX ; echo FOO=$FOO) ; echo FOO=$FOO
产生 FOO=XXX\nFOO=\n
。
source
(又名 .
)?此外,这些天不应再使用反引号,这就是为什么使用 $(command)
更安全的原因之一。
bash
,但可能是其他东西,例如 dash
)而且我没有遇到任何问题如果我必须在命令 args (someargs
) 中使用引号,则麻烦。
您还可以使用 eval
:
FOO=bar eval 'somecommand someargs | somecommand2'
由于这个带有 eval
的答案似乎并不能让每个人都满意,让我澄清一下:当按原样使用时,带有单引号,它是完全安全的。这很好,因为它不会启动外部进程(如接受的答案),也不会在额外的子外壳中执行命令(如其他答案)。
当我们获得一些常规视图时,最好为 eval
提供一个可以取悦所有人的替代方法,并且具有这个快速 eval
“技巧”的所有好处(甚至可能更多!)。只需使用一个功能!使用所有命令定义一个函数:
mypipe() {
somecommand someargs | somecommand2
}
并使用您的环境变量执行它,如下所示:
FOO=bar mypipe
eval
相同的“问题”。
eval
是邪恶的却不了解eval
的邪恶之处的人。也许您毕竟并没有真正理解这个答案(而且确实没有任何问题)。在同一级别上:您会说 ls
是坏的,因为 for file in $(ls)
是坏的吗? (是的,您没有否决接受的答案,也没有发表评论)。 SO有时是一个如此奇怪和荒谬的地方。
eval
的人是邪恶的,却不了解 eval
的邪恶之处,我指的是你的句子:这个答案缺乏谈论 eval
时所有必要的警告和解释。 eval
并不坏或危险;不超过 bash -c
。
eval
不安全的地方,对您来说会更有帮助。在提供的答案中,args 已经被单引号引起来防止变量扩展,所以我认为答案没有问题。
eval
解决方案更清晰,虽然有些冗长。
使用 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
的全部目的是解决所述问题。
一个简单的方法是使用 ;
例如:
ENV=prod; ansible-playbook -i inventories/$ENV --extra-vars "env=$ENV" deauthorize_users.yml --check
command1; command2
在执行 command1 之后依次执行 command2。命令是否成功并不重要。
ENV
。但是,这与其他答案的不同之处在于,这个答案为 shell 中的 all 后续引用定义了 ENV
,而不仅仅是同一行上的引用。我相信最初的问题旨在仅针对同一行的引用更改环境。
;unset ENV
添加到同一行将使其成为一个衬里。但我忽略了它,因为它没有意义。
使用 shell 脚本:
#!/bin/bash
# myscript
FOO=bar
somecommand someargs | somecommand2
> ./myscript
export
;否则 $FOO
将是 shell 变量,而不是环境变量,因此对 somecommand
或 somecommand2
不可见。
不定期副业成功案例分享
somecommand
作为 sudo 运行,则需要将-E
标志传递给 sudo 以传递变量。因为变量会引入漏洞。 stackoverflow.com/a/8633575/1695680FOO_X=foox bash -c 'echo $FOO_X'
按预期工作,但使用特定的 var 名称失败:DYLD_X=foox bash -c 'echo $DYLD_X'
回显空白。两者都使用eval
而不是bash -c