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

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


当前回答

set -a
. ./env.txt
set +a

如果env.txt像这样:

VAR1=1
VAR2=2
VAR3=3
...

解释 -a等价于alleexport。换句话说,shell中的每个变量赋值都被导出到环境中(供多个子进程使用)。更多信息可以在Set内置文档中找到:

-a每个创建或修改的变量或函数都被赋予export属性,并标记为可导出到后续命令的环境。 使用“+”而不是“-”会关闭这些选项。还可以在调用shell时使用这些选项。当前选项集可以在$-中找到。

其他回答

我的.env:

#!/bin/bash
set -a # export all variables

#comments as usual, this is a bash script
USER=foo
PASS=bar

set +a #stop exporting variables

调用:

source .env; echo $USER; echo $PASS

参考https://unix.stackexchange.com/questions/79068/how-to-export-variables-that-are-set-all-at-once

如果你得到一个错误,因为你的一个变量包含了一个包含空格的值,你可以尝试重置bash的IFS(内部字段分隔符)为\n,让bash解释cat .env结果为env可执行文件的参数列表。

例子:

IFS=$'\n'; env $(cat .env) rails c

参见:

http://tldp.org/LDP/abs/html/internalvariables.html#IFSREF https://unix.stackexchange.com/a/196761

我对之前建议的解决方案有问题:

@anubhava的解决方案使得编写bash友好的配置文件非常烦人,而且-你可能不想总是导出你的配置。 @Silas Paul解决方案中断时,你的变量有空格或其他字符,在引号值中工作得很好,但$()使混乱。

以下是我的解决方案,在我看来仍然很糟糕——并且不能解决Silas提出的“只导出到一个孩子”的问题(尽管你可能可以在子shell中运行它来限制范围):

source .conf-file
export $(cut -d= -f1 < .conf-file)

我构建这个脚本动态地源env vars。

我使用这个脚本是因为我不想记住我在项目中使用的每个变量的名称,我不希望导出命令被存储在历史记录中或完整的.env文件导出到git。

#!/bin/sh

filename=".secret"

secret_var () {
    # Parametter 1 : Environnement vars anme

    bash -c 'read -p '$1=' -s voila && echo '$1'"=${voila}" > '$filename''
    export `cat .secret`
    rm $filename
    echo ''
}

public_var () {
    # Parametter 1 : Environnement vars anme

    bash -c 'read -p '$1=' voila && echo '$1'"=${voila}" > '$filename''
    export `cat .secret`
    rm $filename
}

if [ -e $filename ]
then
    echo "A file named '.secret' already exist. Remove it or edit this script."
else
    public_var MY_USER_VAR
    secret_var MY_PASS_VAR
fi

它非常容易使用:

# To add var MY_VAR_NAME to the env
public_var MY_VAR_NAME
# To add var MY_VAR_NAME secretly into the env
secret_var MY_VAR_NAME

例子:

callmarl@LAPTOP ~ % source set_env.sh
MY_USER_VAR=myusername
MY_PASS_VAR=
callmarl@LAPTOP ~ % env
MY_USER_VAR=myusername
MY_PASS_VAR=mysecretpass

当然,如果希望存储值,可以直接使用export,而不是public_var。

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不需要对每个值都导出 一行程序