我试图用来env
为子进程设置环境变量(从另一个源读取,例如文件)。本质上,我正在尝试以下操作:
env VALUE=thisisatest ./somescript.sh
例如,如果somescript.sh
是:
echo $VALUE
然后这将按thisisatest
预期打印。但我想从文件加载变量。我已经到了这一点:
env $(cat .vars | xargs -d '\n') ./somescript.sh
但,当任何变量包含空格(并且引号不能按预期工作)时,我会遇到麻烦。例如:
env $(echo 'VALUE="this is a test"' | xargs -d '\n') ./somescript.sh
会报错
env: is: No such file or directory
并尝试:
env $(echo 'VALUE="thisisatest"' | xargs -d '\n') ./somescript.sh
会给我意想不到的:
"thisisatest"
我认为这可以正常工作,因为运行env VALUE="thisisatest" ./somescript.sh
打印它时不带引号。
从错误中,我了解到由于某种原因 env 不理解引号意味着后面的值应该是一个字符串。但是,我不确定如何以正确解释引号的方式插入这些变量。
任何人都可以提供任何关于我如何实现这一目标的提示吗?
谢谢!
答案1
命令替换中需要使用双引号,否则 shell 将会对命令替换的结果进行字段分割:
$ env "$(echo 'VALUE="this is a test"')" ./somescript.sh
"this is a test"
要从env
文件中读取,您必须让 shell 进行字段分割,但IFS
仅设置为换行符,这样您的命令就不会因空格而中断:
$ IFS='
'
$ env $(cat .vars) ./somescript.sh
如果你想从文件中读取,最好只使用源(又名点) 文件位于somescript.sh
:
#!/bin/bash
. .vars
: The rest of script go here
答案2
这有效:
env -S "`cat .vars`" command
首先,在您的文件中,您需要引用变量值。
VALUE="This has spaces"
然后使用该-S
标志来解析变量(去掉引号)。
env -S "`cat .vars`" command-refers-to-env-vars
当然,您不能$VALUE
在命令中引用,因为该命令是由 shell 评估的事先的的行动env
。为此,您需要使用以下内容:
( . .vars ; echo $VALUE )
括号打开一个子 shell,这样您就不会用 中的所有定义污染您的 shell .vars
。但是,这些变量仅适用于 shell。它们实际上并不在 中env
,因此进程无法通过process.ENV.VALUE
调用getenv("VALUE")
来访问它们env -S
。
您可以将两者结合起来
( . .vars ; env -S "`cat .vars`" command-refers-to-envs $VALUE )
答案3
实际上,有一种更好的方法可以做到这一点,并且您可以毫无问题地声明多个变量。
env {'VALUE=thisisatest','FOO=this is a test'} printenv
答案4
我认为你把事情过于复杂化了。
$ env FOO='this is a test' printenv | egrep -i foo
FOO=this is a test
顺便说一句,引号不是这问题。如果您想要在值中进行变量替换,请使用双引号;如果你想防止变量替换等,请使用单引号。
哎呀,如果适合您的需要,请使用命令替换。使用格式化字符串。两者都用。
$ env FOO=$'this\tis a test' printenv | egrep -i foo | cat -t
FOO=this^Iis a test
$ env FOO="$(echo $'this\tis a test')" printenv | egrep -i foo | cat -t
FOO=this^Iis a test
哎呀,这可能是使用命令替换的更好示例。这个想法是将一些的输出所需命令到变量中,而不仅仅是在不需要的地方无缘无故地使用命令替换。
$ env FOO="$(man man)" printenv | egrep -iA5 foo=
FOO=man(1) man(1)
NAME
man - format and display the on-line manual pages