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

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


当前回答

问题与您的方法是导出在while循环发生在一个子shell,这些变量将不可用在当前shell(父shell的while循环)。

在文件本身中添加export命令:

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

然后你需要在当前shell中的文件中使用:

. ./conf/prac1

OR

source ./conf/prac1

其他回答

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

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

如果你想保持全局环境变量空间不变,我的看法是,我认为这是可取的。

创建一个像这样的脚本:

# !/bin/sh
set -o allexport
source $1
set +o allexport
shift
exec $@

然后像这样使用:

dotenv env-file my-binary

这是我的变种:

  with_env() {
    (set -a && . ./.env && "$@")
  }

与之前方案相比:

它不会泄漏作用域外的变量(来自.env的值不会暴露给调用者) 不clobber设置选项 返回已执行命令的退出代码 使用posix兼容的set -a 用途。而不是源,避免害羞 如果.env加载失败,则不会调用该命令

with_env rails console

我对此的贡献是对@的答案的扩展 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
}

我的要求是:

简单的.env文件,没有导出前缀(为了与dotenv兼容) 支持值在引号中:TEXT="alpha bravo charlie" 支持以#和空行作为前缀的注释 通用的mac/BSD和linux/GNU

完整的工作版本编译自上述答案:

  set -o allexport
  eval $(grep -v '^#' .env | sed 's/^/export /')
  set +o allexport