Shell如何从.env文件设置环境变量
Posted
技术标签:
【中文标题】Shell如何从.env文件设置环境变量【英文标题】:Shell how to set environment variables from .env file 【发布时间】:2017-09-02 04:56:54 【问题描述】:假设我的 .env 文件包含如下行:
USERNAME=ABC
PASSWORD=PASS
不像普通的有export
前缀,所以我不能直接获取文件。
创建从 .env 文件加载内容并将其设置为环境变量的 shell 脚本的最简单方法是什么?
【问题讨论】:
如何定义带空格的值?是var="value with spaces"
,还是var=value with spaces
?两者需要完全不同的方法。
Set environment variables from file的可能重复
【参考方案1】:
这是我用的:
function load_dotenv()
# https://***.com/a/66118031/134904
source <(cat $1 | sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g")
set -a
[ -f "test.env" ] && load_dotenv "test.env"
set +a
如果您使用的是direnv
,请知道它已经支持开箱即用的.env
文件:)
将此添加到您的.envrc
:
[ -f "test.env" ] && dotenv "test.env"
direnv 的标准库文档:https://direnv.net/man/direnv-stdlib.1.html
【讨论】:
【参考方案2】:这将导出 .env 中的所有内容:
export $(xargs <.env)
编辑:这要求环境值没有空格。如果这与您的用例不匹配,您可以使用solution provided by Charles
Edit2:无论如何,我都建议在您的个人资料中添加一个函数,这样您就不必记住set -a
的详细信息或xargs
的工作原理。
【讨论】:
考虑您的.env
是否是使用以下代码创建的:printf '%s\n' 'password="two words"' 'another=foo' >.env
。在这种情况下,传递给export
的参数将是password=two
、words
和another=foo
; words
将不再是 password
的一部分,而是单独作为一个单独的参数(因此该命令将尝试导出名称为 words
的预先存在的变量)。
export $(xargs -L 1 <.env)
会解决这个问题吗@CharlesDuffy ?
我看不出它是怎么做到的——在组装最终的 export
命令之前,命令替换的输出仍然被分词(和全局扩展)。【参考方案3】:
如果您的行是有效的、受信任的 shell但对于export
命令
这需要适当的 shell 引用。因此,如果您有类似foo='bar baz'
这样的行,那么它是合适的,但如果将同一行写成foo=bar baz
,则不合适
set -a # automatically export all variables
source .env
set +a
如果你的行是不是有效的shell
以下读取键/值对,不期望或尊重 shell 引用。
while IFS== read -r key value; do
printf -v "$key" %s "$value" && export "$key"
done
【讨论】:
source .env
基本上可以满足需要。只需确保您的 .env 值中没有空格。
@AdépòjùOlúwáségun,没有set -a
或export
,只为本地shell 设置值,而不为它的子进程设置值。 OP 明确表示“环境变量”,而不是“shell 变量”。 foo=bar
没有设置环境 shell 变量,它设置了一个 shell 变量。
好的,我想我的用例有所不同。感谢您的清晰??
while IFS== read -r key value; do key=`echo $key | sed 's/ *$//g'`; value=`echo $value | sed 's/ *$//g'`; export "$key"="$value"; eval "echo $key = \$$key"; done < .env
做了一个小改动来修剪空格
@RodrigoTorres,该代码有很多错误;我根本不建议使用它。 echo $key
和 echo $value
本身就是错误的——参见 I just assigned a variable, but echo $variable
shows something else!;如果您的值包含*
,您最终可能会得到一个文件名列表。还有一些更有效的方法可用 - 与使用 parameter expansion 剥离空间相比,启动命令替换并在其中运行外部命令的成本更高。【参考方案4】:
找到这个:
http://www.commandlinefu.com/commands/view/12020/export-key-value-pairs-list-as-environment-variables
while read line; do export $line; done < <(cat input)
更新所以我的工作如下:
#!/bin/sh
while read line; do export $line; done < .env
【讨论】:
< <(cat input)
是一种相当复杂的表达方式 < input
,不是吗?
export "$line"
会表现得更好一些,假设它是一行的一个变量,但值能够包含空格。
也就是说,看看这段代码对line="hello world"
的作用——你得到的引号是作为文字数据的一部分导出的,而不是作为语法处理的。这可能没问题,但是由于 OP 说他们不能 source
文件的唯一原因是缺少 export
前缀,所以很可能不会。
另外,您需要将参数-r
添加到read
,这样它就不会破坏反斜杠,并引用"$line"
,这样它的内容就不会得到字符串拆分和glob -在export
看到它们之前展开。以上是关于Shell如何从.env文件设置环境变量的主要内容,如果未能解决你的问题,请参考以下文章
shell变量/环境变量和set/env/export用法_转
请问linux 中如何设置环境变量?在哪个文件下可以查看该环境变量。