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

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


当前回答

sh -ac '. conf-file; yourcommand'

-a开关导出所有变量,以便程序可以使用它们。

与较长的版本set -a;. 配置文件;+一个;yourcommand 使用sh可以确保导出的值不会永久地污染当前环境。它仅为在子shell中运行的程序提供和导出变量。

其他回答

对于那些使用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)"

在这里的几个其他答案中提到了alleexport选项,其中set -a是快捷方式。获取.env确实比遍历行和导出要好,因为它允许注释、空行,甚至命令生成的环境变量。我的.bashrc包含以下内容:

# .env loading in the shell
dotenv () {
  set -a
  [ -f .env ] && . .env
  set +a
}

# Run dotenv on login
dotenv

# Run dotenv on every new directory
cd () {
  builtin cd $@
  dotenv
}

最后,我提出了一个基于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"

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