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' &gt;.env。在这种情况下,传递给export 的参数将是password=twowordsanother=foowords 将不再是 password 的一部分,而是单独作为一个单独的参数(因此该命令将尝试导出名称为 words 的预先存在的变量)。 export $(xargs -L 1 &lt;.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 -aexport,只为本地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 &lt; .env 做了一个小改动来修剪空格 @RodrigoTorres,该代码有很多错误;我根本不建议使用它。 echo $keyecho $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

【讨论】:

&lt; &lt;(cat input) 是一种相当复杂的表达方式 &lt; input,不是吗? export "$line" 会表现得更好一些,假设它是一行的一个变量,但值能够包含空格。 也就是说,看看这段代码对line="hello world" 的作用——你得到的引号是作为文字数据的一部分导出的,而不是作为语法处理的。这可能没问题,但是由于 OP 说他们不能 source 文件的唯一原因是缺少 export 前缀,所以很可能不会。 另外,您需要将参数-r 添加到read,这样它就不会破坏反斜杠,并引用"$line",这样它的内容就不会得到字符串拆分和glob -在export 看到它们之前展开。

以上是关于Shell如何从.env文件设置环境变量的主要内容,如果未能解决你的问题,请参考以下文章

shell变量/环境变量和set/env/export用法_转

linux下配置自己的环境变量文件my_env.sh

请问linux 中如何设置环境变量?在哪个文件下可以查看该环境变量。

Node环境变量Process.env

如何从.env文件获取环境变量到docker-compose.yml?

linux :环境变量小结