Set environment variables from file of key/pair values
tl;dr:如何将一组键/值对从文本文件导出到shell环境中?
下面是问题的原始版本,并举例说明。
我正在用bash编写一个脚本,它解析某个文件夹中包含3个变量的文件,这是其中之一:
1 2 3 | MINIENTREGA_FECHALIMITE="2011-03-31" MINIENTREGA_FICHEROS="informe.txt programa.c" MINIENTREGA_DESTINO="./destino/entrega-prac1" |
此文件存储在/conf/prac1中。
然后,脚本minenterga.sh使用以下代码解析文件:
1 2 3 | cat ./conf/$1 | while read line; do export $line done |
但当我在命令行中执行
我也尝试过使用
也许还有其他方法可以做到这一点,我只需要使用我传递的文件的环境变量作为脚本的参数。
这可能会有所帮助:
1 | export $(cat .env | xargs) && rails c |
我之所以使用它,是因为我想在Rails控制台中测试
加布里耶夫想出了一个很好的方法来保持变量的局部性。这解决了从一个项目到另一个项目的潜在问题。
1 | env $(cat .env | xargs) rails |
我用
更新:
若要忽略以
1 | export $(grep -v '^#' .env | xargs) |
如果您想要
1 | unset $(grep -v '^#' .env | sed -E 's/(.*)=.*/\1/' | xargs) |
更新:
要使用空格处理值,请使用:
1 2 | export $(grep -v '^#' .env | xargs -d ' ') |
在GNU系统上或:
1 | export $(grep -v '^#' .env | xargs -0) |
在BSD系统上。
1 2 3 | set -o allexport source conf-file set +o allexport |
您的方法的问题是
在文件本身中添加
1 2 3 | export MINIENTREGA_FECHALIMITE="2011-03-31" export MINIENTREGA_FICHEROS="informe.txt programa.c" export MINIENTREGA_DESTINO="./destino/entrega-prac1" |
然后,您需要在当前shell的文件中使用以下方法进行源代码:
1 | . ./conf/prac1 |
或
1 | source ./conf/prac1 |
1 2 3 | set -a . ./env.txt set +a |
如果
1 2 3 4 | VAR1=1 VAR2=2 VAR3=3 ... |
这里还有几个答案提到了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # .env loading in the shell dotenv () { set -a [ -f .env ] && . .env set +a } # Run dotenv on login dotenv # Run dotenv on every new directory cd () { builtin cd $@ dotenv } |
1 | eval $(cat .env | sed 's/^/export /') |
这是另一个
1 | source <(sed -E -n 's/[^#]+/export &/ p' ~/.env) |
这将添加导出,保留以注释开头的行的注释。
Env含量1 2 | A=1 #B=2 |
样品运行
1 2 3 | $ sed -E -n 's/[^#]+/export &/ p' ~/.env export A=1 #export B=2 |
我发现这在构建这样一个文件以便在SystemD单元文件中加载时特别有用,使用
我已经对用户4040650的答案投了赞成票,因为它既简单又允许在文件中添加注释(即以开头的行),这对我来说是非常可取的,因为可以添加解释变量的注释。只是在原始问题的上下文中重写。
如果按照指示调用脚本:
1 2 3 4 5 6 | set -a # export all variables created next source $1 set +a # stop exporting # test that it works echo"Ficheros: $MINIENTREGA_FICHEROS" |
以下是从集合文档中提取的:
This builtin is so complicated that it deserves its own section. set
allows you to change the values of shell options and set the
positional parameters, or to display the names and values of shell
variables.set [--abefhkmnptuvxBCEHPT] [-o option-name] [argument …] set
[+abefhkmnptuvxBCEHPT] [+o option-name] [argument …]If no options or arguments are supplied, set displays the names and values of all shell
variables and functions, sorted according to the current locale, in a
format that may be reused as input for setting or resetting the
currently-set variables. Read-only variables cannot be reset. In POSIX
mode, only shell variables are listed.When options are supplied, they set or unset shell attributes.
Options, if specified, have the following meanings:-a Each variable or function that is created or modified is given the export attribute and marked for export to the environment of
subsequent commands.
这也是:
Using ‘+’ rather than ‘-’ causes these options to be turned off. The
options can also be used upon invocation of the shell. The current set
of options may be found in $-.
这将保存/恢复您的原始选项,无论它们是什么。
使用
改进塞拉斯·保罗的回答
在子shell上导出变量使其成为命令的本地变量。
更简单:
另一种选择(不必运行
1 | export $(cat .env | sed -e /^$/d -e /^#/d | xargs) |
最后,如果你想让你的生活变得轻松,把它加到你的
(确保重新加载bash设置!!!!
在其他答案的基础上,这里有一种方法可以只导出文件中的一部分行,包括带有空格的值,如
1 2 3 | set -a . <(grep '^[ ]*PREFIX_' conf-file) set +a |
您可以使用原始脚本来设置变量,但需要按以下方式调用它(使用独立点):
1 | . ./minientrega.sh |
另外,
下面是一个工作示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | > 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 |
我的要求是:
- 不带
export 前缀的简单.env文件(用于与dotenv兼容) - 引号中的支持值:text="Alpha Bravo Charlie"
- 以和空行为前缀的支持注释
- 适用于Mac/BSD和Linux/GNU的通用
根据以上答案编制的完整工作版本:
1 2 3 | set -o allexport eval $(grep -v '^#' .env | sed 's/^/export /') set +o allexport |
我对先前建议的解决方案有异议:
- @Anubhava的解决方案使得编写对bash友好的配置文件非常恼人,而且-您可能不希望总是导出您的配置。
- @Silas-Paul解决方案会在变量具有在引用值中工作良好的空格或其他字符时中断,但
$() 会使问题变得一团糟。
这是我的解决方案,它在IMO中仍然相当糟糕,并且没有解决Silas解决的"只导出一个孩子"问题(尽管您可能可以在子shell中运行它来限制范围):
1 2 | source .conf-file export $(cut -d= -f1 < .conf-file) |
值中有空格
这里有很多很好的答案,但我发现它们都缺乏对价值空间的支持:
1 | DATABASE_CLIENT_HOST=host db-name db-user 0.0.0.0/0 md5 |
我发现了两种解决方案,它们都支持空行和注释,具有这样的价值。
一个基于sed和@javier buzzi的答案:
1 | source <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x"&"/g' .env) |
根据@john1024答案,在一个循环中有一个读行
1 | while read -r line; do declare -x"$line"; done < <(egrep -v"(^#|^\s|^$)" .env) |
这里的关键是使用
我在尝试在shell中重用docker
我不能完全让它与posix兼容,但这里有一个可以在类似bash的shell中工作(在osx 10.12.5上的zsh和Ubuntu 14.04上的bash中测试):
1 | while read -r l; do export"$(sed 's/=.*$//' <<<$l)"="$(sed -E 's/^[^=]+=//' <<<$l)"; done < <(grep -E -v '^\s*(#|$)' your-env-file) |
在示例中,它不会处理上面链接的文档中的三个案例:
bash: export: `123qwe=bar': not a valid identifier bash: export: `org.spring.config=something': not a valid identifier - 它不会处理直通语法(一个裸的
FOO )
如果因为某个变量包含一个包含空格的值而出错,可以尝试将bash的EDOCX1(内部字段分隔符)重置为
例子:
1 2 | IFS=$' '; env $(cat .env) rails c |
参见:
- http://tldp.org/ldp/abs/html/internalvariables.html ifsref
- https://unix.stackexchange.com/a/196761
我的.EnV:
1 2 3 4 5 6 7 8 | #!/bin/bash set -a # export all variables #comments as usual, this is a bash script USER=foo PASS=bar set +a #stop exporting variables |
调用:
1 | source .env; echo $USER; echo $PASS |
参考https://unix.stackexchange.com/questions/79068/how-to-export-variables-that-are-set-all-at-once