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,但同样的问题仍然适用
也许还有其他方法可以做到这一点,我只需要使用我传递的文件的环境变量作为脚本的参数。
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不需要对每个值都导出
一行程序
这可能会有帮助:
export $(cat .env | xargs) && rails c
我使用这个的原因是如果我想在我的rails控制台中测试。env的东西。
Gabrielf想出了一个保持变量局部的好方法。这解决了从一个项目到另一个项目时的潜在问题。
env $(cat .env | xargs) rails
我已经用bash 3.2.51(1)-release测试了这一点
更新:
要忽略以#开头的行,使用这个(感谢Pete的评论):
export $(grep -v '^#' .env | xargs)
如果你想取消文件中定义的所有变量,使用这个:
unset $(grep -v '^#' .env | sed -E 's/(.*)=.*/\1/' | xargs)
更新:
要处理带有空格的值,请使用:
export $(grep -v '^#' .env | xargs -d '\n')
在GNU系统上——或者:
export $(grep -v '^#' .env | xargs -0)
在BSD系统上。
从这个答案中,你可以自动检测操作系统:
export-env.sh
#!/bin/sh
## Usage:
## . ./export-env.sh ; $COMMAND
## . ./export-env.sh ; echo ${MINIENTREGA_FECHALIMITE}
unamestr=$(uname)
if [ "$unamestr" = 'Linux' ]; then
export $(grep -v '^#' .env | xargs -d '\n')
elif [ "$unamestr" = 'FreeBSD' ] || [ "$unamestr" = 'Darwin' ]; then
export $(grep -v '^#' .env | xargs -0)
fi
值中的空格
这里有很多很好的答案,但我发现它们都缺乏对值中空白的支持:
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程序员,我只是狼吞虎咽地把这些放在一起,它对我来说仍然是魔法:)