【问题标题】:Shell how to set environment variables from .env fileShell如何从.env文件设置环境变量
【发布时间】:2017-09-02 04:56:54
【问题描述】:

假设我的 .env 文件包含如下行:

USERNAME=ABC
PASSWORD=PASS

不像普通的有export前缀,所以我不能直接获取文件。

创建从 .env 文件加载内容并将其设置为环境变量的 shell 脚本的最简单方法是什么?

【问题讨论】:

  • 如何定义带空格的值?是var="value with spaces",还是var=value with spaces?两者需要完全不同的方法。

标签: shell


【解决方案1】:

这是我用的:

function load_dotenv(){
  # https://stackoverflow.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 看到它们之前展开。
    猜你喜欢
    • 2021-08-19
    • 1970-01-01
    • 2022-07-20
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 1970-01-01
    • 2015-10-21
    相关资源
    最近更新 更多