TL;DR:如何从文本文件中导出一组键/值对到shell环境中?


为了记录在案,以下是问题的原始版本,并附有示例。

我在bash中写了一个脚本,它在某个文件夹中解析带有3个变量的文件,这是其中之一:

MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.c"
MINIENTREGA_DESTINO="./destino/entrega-prac1"

该文件的存放路径为。/conf/prac1

我的脚本minientrega.sh然后使用以下代码解析文件:

cat ./conf/$1 | while read line; do
    export $line
done

但是当我在命令行中执行minientrega.sh prac1时,它不会设置环境变量

我也尝试使用source ./conf/$1,但同样的问题仍然适用

也许还有其他方法可以做到这一点,我只需要使用我传递的文件的环境变量作为脚本的参数。


当前回答

值中的空格

这里有很多很好的答案,但我发现它们都缺乏对值中空白的支持:

DATABASE_CLIENT_HOST=host db-name db-user 0.0.0.0/0 md5

我发现了2个解决方案,这些值支持空行和注释。

一个基于sed和@javier-buzzi的答案:

source <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x "&"/g' .env)

和一个读行在循环基于@john1024答案

while read -r line; do declare -x "$line"; done < <(egrep -v "(^#|^\s|^$)" .env)

这里的关键是使用声明-x并将line放在双引号中。我不知道为什么,但当你将循环代码重新格式化为多行时,它不会工作-我不是bash程序员,我只是狼吞虎咽地把这些放在一起,它对我来说仍然是魔法:)

其他回答

我发现最有效的方法是:

export $(xargs < .env)

解释

当我们有一个这样的.env文件时:

key=val
foo=bar

运行xargs < .env将得到key=val foo=bar

因此我们将得到export key=val foo=bar,这正是我们所需要的!

限制

它不处理值中有空格的情况。像env这样的命令会产生这种格式。——@Shardj

值中的空格

这里有很多很好的答案,但我发现它们都缺乏对值中空白的支持:

DATABASE_CLIENT_HOST=host db-name db-user 0.0.0.0/0 md5

我发现了2个解决方案,这些值支持空行和注释。

一个基于sed和@javier-buzzi的答案:

source <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x "&"/g' .env)

和一个读行在循环基于@john1024答案

while read -r line; do declare -x "$line"; done < <(egrep -v "(^#|^\s|^$)" .env)

这里的关键是使用声明-x并将line放在双引号中。我不知道为什么,但当你将循环代码重新格式化为多行时,它不会工作-我不是bash程序员,我只是狼吞虎咽地把这些放在一起,它对我来说仍然是魔法:)

修改自@Dan Kowalczyk

我把它放在~/.bashrc中。

set -a
. ./.env >/dev/null 2>&1
set +a

与Oh-my-Zsh的dotenv插件非常好的交叉兼容。(有Oh-my-bash,但它没有dotenv插件。)

SAVE=$(set +o | grep allexport) && set -o allexport && ..环境;评估“$SAVE”

这将保存/恢复您的原始选项,无论它们是什么。

使用set -o alleexport的优点是可以在没有正则表达式的情况下正确地跳过注释。

Set +o本身以bash稍后可以执行的格式输出所有当前选项。同样方便的是:set -o本身以人类友好的格式输出所有当前选项。

在其他答案的基础上,这里是一种只导出文件中一行的子集的方法,包括像PREFIX_ONE="a word"这样的空格值:

set -a
. <(grep '^[ ]*PREFIX_' conf-file)
set +a