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 $(grep -v '^#' envfilename | xargs -L 1  -d '\r' -d '\r\n')

这在CentOS上就像一个魅力;当你遇到\r被附加到加载变量的问题时。它还负责注释和空白。

其他回答

以下是我的看法。我有以下要求:

忽略注释行 值中允许有空格 允许空行 能够在默认为.env时传递自定义env文件 允许导出以及内联运行命令 如果env文件不存在,退出

source_env() {
  env=${1:-.env}
  [ ! -f "${env}" ] && { echo "Env file ${env} doesn't exist"; return 1; }
  eval $(sed -e '/^\s*$/d' -e '/^\s*#/d' -e 's/=/="/' -e 's/$/"/' -e 's/^/export /' "${env}")
}

将函数保存到.bash_profile或等效文件后的用法:

source_env                # load default .env file
source_env .env.dev       # load custom .env file
(source_env && COMMAND)   # run command without saving vars to environment

受到哈维尔和其他一些评论的启发。

最后,我提出了一个基于allexport + source的解决方案。这里的主要思想是防止重写现有变量。

function load_env_file() {
    local FILE_PATH="${1}"
    local EXISTENT_VARS=$(declare)

    set -o allexport
    source "${FILE_PATH}"
    set +o allexport

    # errors are supressed as "declare" returns also readonly vars which are not overridable
    eval "${EXISTENT_VARS}" 2> /dev/null || true
}

# Usage example:
load_env_file "path/to/.env"

如何保存变量:

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

如何装载它们

source myvariables.sh

在其他答案的基础上,这里是一种只导出文件中一行的子集的方法,包括像PREFIX_ONE="a word"这样的空格值:

set -a
. <(grep '^[ ]*PREFIX_' conf-file)
set +a

如果你得到一个错误,因为你的一个变量包含了一个包含空格的值,你可以尝试重置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