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

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


当前回答

对于那些使用ruby的人,我制作了一个名为dotenv_export的小型实用工具gem。

使用

Dotenv_export是一个小的实用程序命令,它读取。env文件,并使用ruby dotenv实现将其转换为导出语句。

# first install `dotenv_export`
gem install dotenv_export

然后,在你的.bash_profile中,或者任何你想要加载环境变量的shell环境中,执行以下命令:

eval "$(dotenv-export /path/to/.env)"

其他回答

首先,创建一个环境文件,其中包含如下所示环境的所有键-值对,并将其命名为任何您喜欢的名称,在我的示例中为env_var.env

MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.c"
MINIENTREGA_DESTINO="./destino/entrega-prac1"

然后创建一个脚本,该脚本将导出python环境的所有环境变量,如下所示,并将其命名为export_env.sh

#!/usr/bin/env bash

ENV_FILE="$1"
CMD=${@:2}

set -o allexport
source $ENV_FILE
set +o allexport

$CMD

该脚本将第一个参数作为环境文件,然后导出该文件中的所有环境变量,然后在此之后运行该命令。

用法:

./export_env.sh env_var.env python app.py

一种zsh方法是在运行中创建一个文件,在每一行的开头都有导出,在subshell中来源它,并执行你的命令:

$ cat env.db
VAR=" value = with!! special chars #"
$ ( . =(sed 's/^[^#]/export \0/' < env.db) && echo $VAR) 
 value = with!! special chars #
$ echo $VAR

$

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

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

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

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

如果env支持-S选项,则可以使用换行符或转义字符,如\n或\t(参见env):

env -S "$(cat .env)" command

.env文件示例:

KEY="value with space\nnewline\ttab\tand
multiple
lines"

测试:

env -S "$(cat .env)" sh -c 'echo "$KEY"'

我对此的贡献是对@的答案的扩展 User4040650允许在git repo中轻松使用。它将尝试从当前目录中获取。env文件,如果不存在,则从你所在的git repo中获取。env文件。如果你已经cd到子目录中,那么就不需要源../../,这是很有帮助的。环境之类的。

我把它放在我的.bashrc中,所以我只需要在需要的地方调用setenv

setenv() {
  local env_path
  if { [ -f .env ] && env_path='.env'; } || { env_path=$(git  rev-parse --show-toplevel 2>/dev/null)/.env && [ -f "$env_path" ]; }; then
    echo "sourcing $env_path"
    set -o allexport
    source "$env_path"
    set +o allexport
  else
    echo "No env file found"
  fi
}