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,但同样的问题仍然适用
也许还有其他方法可以做到这一点,我只需要使用我传递的文件的环境变量作为脚本的参数。
简单:
获取文件的内容
删除任何空行(以防你分开一些东西)
删除任何注释(以防你添加了一些…)
将export添加到所有行
对整个事件进行评估
eval (cat .env美元| sed - e / ^ $ / d - e / ^ # / d - e ' s / ^ /出口/ ')
另一个选择(你不必运行eval(感谢@Jaydeep)):
export $(cat .env | sed -e /^$/d -e /^#/d | xargs)
最后,如果你想让你的生活真的很简单,把这个添加到你的~/.bash_profile:
函数source_envfile() {export $(cat $1 | sed -e /^$/d -e /^#/d | xargs);}
(请务必重新加载bash设置!!~ /来源。bash_profile或. .只要新建一个标签/窗口,问题就解决了),你这样叫它:source_envfile .env
如果您想让exec作为脚本的最后一个命令,那么您可以使用execlineb解释器。这是脚本的最后一行:
#!/bin/sh
...
exec envfile -I /etc/default/bla envfile /etc/default/bla-bla my_cmd
envfile……是来自execline套件的命令,它们依赖于“链加载”。
顺便说一句,一旦你进入这个兔子洞,你可能会发现你不再需要壳了(…-)使用execlineb解释器而不是shell来启动服务,以最小的开销是非常有用的,即:
#!/bin/execlineb
...
envfile -I /etc/default/bla
envfile /etc/default/bla-bla
my_cmd
我用这个:
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)