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,但同样的问题仍然适用
也许还有其他方法可以做到这一点,我只需要使用我传递的文件的环境变量作为脚本的参数。
我用这个:
source <(cat .env \
| sed -E '/^\s*#.*/d' \
| tr '\n' '\000' \
| sed -z -E 's/^([^=]+)=(.*)/\1\x0\2/g' \
| xargs -0 -n2 bash -c 'printf "export %s=%q;\n" "${@}"' /dev/null)
首先删除评论:
sed -E '/^\s*#.*/d'
然后转换为空分隔符而不是换行符:
tr '\n' '\000'
然后用null替换equal:
sed -z -E 's/^([^=]+)=(.*)/\1\x0\2/g'
然后打印对到有效的带引号的bash导出(使用bash printf for %q):
xargs -0 -n2 bash -c 'printf "export %s=%q;\n" "${@}"' /dev/null
最后是来源。
它应该适用于所有特殊字符的所有情况。
当我试图在shell中重用Docker -env-files时,我遇到了这个线程。它们的格式与bash不兼容,但很简单:name=value,没有引号,没有替换。它们还会忽略空行和#注释。
我不能完全让它与posix兼容,但这里有一个应该在bash-like shell中工作(在OSX 10.12.5的zsh和Ubuntu 14.04的bash中测试):
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':不是有效的标识符
Bash: export: `org.spring。Config =something':不是有效的标识符
并且它不会处理传递语法(一个纯FOO)
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