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,但同样的问题仍然适用
也许还有其他方法可以做到这一点,我只需要使用我传递的文件的环境变量作为脚本的参数。
我在Mac上使用docker-compose和.env文件,并想将.env导入到我的bash shell中(用于测试),这里的“最佳”答案是在以下变量上出错:
.env
NODE_ARGS=--expose-gc --max_old_space_size=2048
解决方案
所以我最终使用eval,并将env var defs包装在单引号中。
eval $(grep -v -e '^#' .env | xargs -I {} echo export \'{}\')
Bash的版本
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
以下是我的看法。我有以下要求:
忽略注释行
值中允许有空格
允许空行
能够在默认为.env时传递自定义env文件
允许导出以及内联运行命令
如果env文件不存在,退出
source_env() {
env=${1:-.env}
[ ! -f "${env}" ] && { echo "Env file ${env} doesn't exist"; return 1; }
eval $(sed -e '/^\s*$/d' -e '/^\s*#/d' -e 's/=/="/' -e 's/$/"/' -e 's/^/export /' "${env}")
}
将函数保存到.bash_profile或等效文件后的用法:
source_env # load default .env file
source_env .env.dev # load custom .env file
(source_env && COMMAND) # run command without saving vars to environment
受到哈维尔和其他一些评论的启发。
source的问题在于它要求文件具有正确的bash语法,而一些特殊字符会破坏它:=、"、'、<、>等。所以在某些情况下你可以
source development.env
它会起作用的。
然而,这个版本可以承受值中的所有特殊字符:
set -a
source <(cat development.env | \
sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g")
set +a
解释:
-a意味着每个bash变量都将成为环境变量
/^#/d删除注释(以#开头的字符串)
/^\s*$/d删除空字符串,包括空格
"s/'/'\\\ " /g"将每个单引号替换为'\ ",这是bash中的一个生成引号的技巧序列:)
"s/=\(.*\)/='\1'/g"将每个a=b转换为a='b'
因此,你可以使用特殊字符:)
要调试这段代码,将source替换为cat,您将看到该命令产生的结果。
t=$(mktemp) && export -p > "$t" && set -a && . ./.env && set +a && . "$t" && rm "$t" && unset t
它是如何工作的
Create temp file.
Write all current environment variables values to the temp file.
Enable exporting of all declared variables in the sources script to the environment.
Read .env file. All variables will be exported into current environment.
Disable exporting of all declared variables in the sources script to the environment.
Read the contents of the temp file. Every line would have declare -x VAR="val" that would export each of the variables into environment.
Remove temp file.
Unset the variable holding temp file name.
特性
保留环境中已设置的变量的值
.env可以有注释
.env可以有空行
.env不像其他答案那样需要特殊的页眉或页脚(set -a和set +a)
.env不需要对每个值都导出
一行程序