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.
这可能会有帮助:
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
posix兼容的解决方案(不依赖于bash)
正如其他人所注意到的,在这里使用for/while循环的问题是,变量在shell及其子shell之间不共享。然而,我们能做的是使用args/stdin/stdout在shell之间传递文本。
在subshell中设置环境变量在我们获取脚本源代码时是没有帮助的
变量不会向上传播,但我们知道可以将文本发送回去。这个文本也可以是代码,我们可以用eval在当前shell中求值。
如果我们生成用于设置所有环境变量的代码,然后对结果进行计算呢?
create_exports_script() {
echo "$1" | while read line; do
echo "export $line"
done
}
file_contents=$(cat "./conf/myconf.env")
eval $(create_exports_script "$file_contents")
bash中的这种函数式元编程非常灵活。您还可以用这种方式生成bash/sh以外的其他语言。