如何从单个进程的文本文件 (.env) 加载变量而不导出变量?

如何从单个进程的文本文件 (.env) 加载变量而不导出变量?

注意:这个一般性主题似乎在多个 SE 网站上都被令人作呕地涵盖,但请仔细阅读所有详细信息 - 我没有发现任何涵盖下面描述的所有标准的问题。

zsh另外:我在下面的示例中使用。我希望有一个符合 POSIX 标准的解决方案,但这并不是一个硬性要求:能够工作bash并且zsh足够好的东西。

这是一个帮助澄清问题标题的示例:

假设我有以下两个文件:

% ls -AF
.env    printenv*

% cat printenv
echo $LOCAL_MESSAGE_1
echo $LOCAL_MESSAGE_2

% cat .env
LOCAL_MESSAGE_1="hello world"
LOCAL_MESSAGE_2="goodnight moon"

我想执行该脚本printenv并在中看到以下内容stdout

hello world
goodnight moon

如果这些变量在我的环境中不存在,脚本将打印空行(如预期):

% unset LOCAL_MESSAGE_1

% unset LOCAL_MESSAGE_2

% ./printenv


如果我在执行脚本之前设置变量,它们将可供脚本使用,但仅限于该单个进程,而不适用于从同一 shell 启动的任何后续进程:

% LOCAL_MESSAGE_1="hello world" LOCAL_MESSAGE_2="goodnight moon" ./printenv
hello world
goodnight moon

% ./printenv


所以,我的问题是:如何根据以下标准复制上一个示例中的行为?

  1. printenv在当前 shell 中不加修改地运行— 而不是在子 shell 中运行(感谢鲁迪克) — 并获得所需的输出,同时也
  2. 从文件加载变量.env,同时还
  3. 保持该进程调用的本地变量:它们将在 shell 环境和后续进程中保持未设置状态不需要unset他们

我可以使用什么单行语法来完成此任务?应该用什么代替下面的问号才能满足上述标准?

% ?????????? ./printenv
hello world
goodnight moon

答案1

您是否尝试过在子外壳(in )中运行它们bash?喜欢

( . .env; . ./printenv )
hello world
goodnight moon

这样,printenv仅为脚本设置 LOCAL 变量,而父 shell 的环境保持不变。

根据您的新的扩展要求(无子外壳),请尝试使用 (不受欢迎,危险) 的方法eval

eval $(< .env) ./printenv
hello world
goodnight moon

它将变量的定义和命令放在一行中,然后eval执行该行。

答案2

runenv(这是名为的包的一部分罪犯- 又名肇事者):

runenv env_file command

将要
command在当前 shell 中运行而不进行修改(而不是在子 shell 中)并获得所需的输出,同时还从 加载变量env_file,同时还保留该进程调用的本地变量:它们将在 shell 环境和后续 shell 环境中保持未设置状态进程无需取消设置”

答案3

您可以使用“.script”语法将脚本来源到 shell:

。 .env && . ./printenv

您还可以将“. .env”添加到 printenv 脚本的开头。然后你将能够执行 printenv :

./printenv

“printenv”不是一个好的名称选择,因为它由 shell 使用。

相关内容