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,但同样的问题仍然适用

也许还有其他方法可以做到这一点,我只需要使用我传递的文件的环境变量作为脚本的参数。


当前回答

如何保存变量:

printenv | sed 's/\([a-zA-Z0-9_]*\)=\(.*\)/export \1="\2"/' > myvariables.sh

如何装载它们

source myvariables.sh

其他回答

SAVE=$(set +o | grep allexport) && set -o allexport && ..环境;评估“$SAVE”

这将保存/恢复您的原始选项,无论它们是什么。

使用set -o alleexport的优点是可以在没有正则表达式的情况下正确地跳过注释。

Set +o本身以bash稍后可以执行的格式输出所有当前选项。同样方便的是:set -o本身以人类友好的格式输出所有当前选项。

当我试图在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)

如果您想让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

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以外的其他语言。

-o allexport允许导出以下所有变量定义。+o allexport禁用此功能。

set -o allexport
source conf-file
set +o allexport