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,但同样的问题仍然适用

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


当前回答

试试这样的方法

for line in `cat your_env_file`; do if [[ $line != \#* ]];then export $line; fi;done

其他回答

我的要求是:

简单的.env文件,没有导出前缀(为了与dotenv兼容) 支持值在引号中:TEXT="alpha bravo charlie" 支持以#和空行作为前缀的注释 通用的mac/BSD和linux/GNU

完整的工作版本编译自上述答案:

  set -o allexport
  eval $(grep -v '^#' .env | sed 's/^/export /')
  set +o allexport

我对之前建议的解决方案有问题:

@anubhava的解决方案使得编写bash友好的配置文件非常烦人,而且-你可能不想总是导出你的配置。 @Silas Paul解决方案中断时,你的变量有空格或其他字符,在引号值中工作得很好,但$()使混乱。

以下是我的解决方案,在我看来仍然很糟糕——并且不能解决Silas提出的“只导出到一个孩子”的问题(尽管你可能可以在子shell中运行它来限制范围):

source .conf-file
export $(cut -d= -f1 < .conf-file)

如果env支持-S选项,则可以使用换行符或转义字符,如\n或\t(参见env):

env -S "$(cat .env)" command

.env文件示例:

KEY="value with space\nnewline\ttab\tand
multiple
lines"

测试:

env -S "$(cat .env)" sh -c 'echo "$KEY"'

我的.env文件是这样的:

DATABASE_URI="postgres://sa:***@localhost:5432/my_db"
VARIABLE_1="SOME_VALUE"
VALIABLE_2="123456788"

使用@henke的方法,导出的值最终包含引号“

"postgres://sa:***@localhost:5432/my_db"
"SOME_VALUE"
"123456788"

但我希望导出的值只包含:

postgres://sa:***@localhost:5432/my_db
SOME_VALUE
123456788

为了解决这个问题,我编辑命令删除引号:

export $(grep -v '^#' dev.env | tr --delete '"' | xargs -d '\n')

你可以使用你的原始脚本来设置变量,但你需要以以下方式调用它(独立的点):

. ./minientrega.sh

此外,在读取方法时,cat |可能会出现问题。我建议在读行时使用这种方法;做……done < $FILE。

下面是一个工作示例:

> cat test.conf
VARIABLE_TMP1=some_value

> cat run_test.sh
#/bin/bash
while read line; do export "$line";
done < test.conf
echo "done"

> . ./run_test.sh
done

> echo $VARIABLE_TMP1
some_value