从键/值对文件中设置环境变量

太长别读:如何将一组键/值对从文本文件导出到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; doexport $linedone

但是当我在命令行中执行minientrega.sh prac1时,它不会设置环境变量

我也尝试使用source ./conf/$1,但同样的问题仍然适用

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

777409 次浏览

您的方法的问题是while循环中的export发生在子shell中,并且这些变量在当前shell(这时候循环的父shell)中不可用。

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

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

然后,您需要使用以下命令在当前shell中获取文件:

. ./conf/prac1

source ./conf/prac1

这可能会有帮助:

export $(cat .env | xargs) && rails c

我使用这个的原因是如果我想在我的rails控制台中测试.env的东西。

加布里埃尔提出了一个保持变量本地的好方法。这解决了从一个项目到另一个项目时的潜在问题。

env $(cat .env | xargs) rails

我用bash 3.2.51(1)-release测试过这个


更新时间:

要忽略以#开头的行,请使用此(感谢Pete的评论):

export $(grep -v '^#' .env | xargs)

如果您想将文件中定义的所有变量unset,请使用:

unset $(grep -v '^#' .env | sed -E 's/(.*)=.*/\1/' | xargs)

更新时间:

要同时处理带空格的值,请使用:

export $(grep -v '^#' .env | xargs -d '\n')

在GNU系统上-或:

export $(grep -v '^#' .env | xargs -0)

在BSD系统上。


这个答案开始,您可以使用以下命令自动检测操作系统:

export-env.sh

#!/bin/sh
## Usage:##   . ./export-env.sh ; $COMMAND##   . ./export-env.sh ; echo ${MINIENTREGA_FECHALIMITE}
unamestr=$(uname)if [ "$unamestr" = 'Linux' ]; then
export $(grep -v '^#' .env | xargs -d '\n')
elif [ "$unamestr" = 'FreeBSD' ] || [ "$unamestr" = 'Darwin' ]; then
export $(grep -v '^#' .env | xargs -0)
fi

您可以使用原始脚本来设置变量,但您需要以以下方式调用它(使用独立的点):

. ./minientrega.sh

cat | while read方法也可能存在问题。我建议使用方法while read line; do .... done < $FILE

下面是一个工作示例:

> cat test.confVARIABLE_TMP1=some_value
> cat run_test.sh#/bin/bashwhile read line; do export "$line";done < test.confecho "done"
> . ./run_test.shdone
> echo $VARIABLE_TMP1some_value

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

  • @anubhava的解决方案使得编写bash友好的配置文件非常烦人非常快,而且-您可能不想总是导出您的配置。
  • 当您的变量具有空格或其他字符在引用值中运行良好时,@Silas Paul解决方案会中断,但$()会弄得一团糟。

这是我的解决方案,在我看来仍然非常糟糕-并且不能解决Silas解决的“仅导出到一个孩子”问题(尽管您可能可以在子shell中运行它以限制范围):

source .conf-fileexport $(cut -d= -f1 < .conf-file)
eval $(cat .env | sed 's/^/export /')

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

set -o allexportsource conf-fileset +o allexport
########################################################### CAUTION: this does not work when executed from a script,# it must be copied to and run from the current terminal!##########################################################

SAVE=$(set +o | grep allexport) && set -o allexport && . .env; eval "$SAVE"

这将保存/恢复您的原始选项,无论它们是什么。

使用set -o allexport的优点是可以在没有正则表达式的情况下正确跳过注释。

set +o本身以bash稍后可以执行的格式输出您当前的所有选项。同样方便的是:set -o本身以人类友好的格式输出您当前的所有选项。

改进Silas Paul的回答

在子shell上导出变量使它们成为命令的本地变量。

(export $(cat .env | xargs) && rails c)

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

# .env loading in the shelldotenv () {set -a[ -f .env ] && . .envset +a}
# Run dotenv on logindotenv
# Run dotenv on every new directorycd () {builtin cd $@dotenv}

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

示例:

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

另见:

这是另一个sed解决方案,它不运行val或需要ruby:

source <(sed -E -n 's/[^#]+/export &/ p' ~/.env)

这增加了导出,将注释保留在以注释开头的行上。

. env内容

A=1#B=2

样品运行

$ sed -E -n 's/[^#]+/export &/ p' ~/.envexport A=1#export B=2

我发现这在构建这样的文件以加载system d单元文件,带#0时特别有用。

我赞成user4040650的答案,因为它既简单,又允许在文件中进行注释(即以#开头的行),这对我来说非常理想,因为可以添加解释变量的注释。只需在原始问题的上下文中重写。

如果脚本被调用为minientrega.sh prac1,那么minientrega.sh可能有:

set -a # export all variables created nextsource $1set +a # stop exporting
# test that it worksecho "Ficheros: $MINIENTREGA_FICHEROS"

以下是从设置留档中提取的:

这个内置程序非常复杂,它应该有自己的部分。设置允许您更改shell选项的值并设置位置参数,或显示shell的名称和值变量。

set[--abefhkmnptuvxBCEHPT][-o选项名称][参数…]set[+abefhkmnptuvxBCEHPT][+o option-name][参数…]

如果没有提供选项或参数,则set显示所有shell的名称和值变量和函数,根据当前语言环境排序,在一个可以重复用作设置或重置输入的格式当前设置的变量。只读变量不能重置。在POSIX中模式,仅列出shell变量。

当提供选项时,它们设置或取消设置shell属性。如果指定了选项,则具有以下含义:

-a创建或修改的每个变量或函数都被赋予导出属性并标记为导出到环境后续命令。

还有这个:

使用'+'而不是'-'会导致这些选项被关闭选项也可以在调用shell时使用。当前集的选项可以在$-中找到。

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

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

我的. env:

#!/bin/bashset -a # export all variables
#comments as usual, this is a bash scriptUSER=fooPASS=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

当我尝试在shell中重用Docker--env-file时,我遇到了这个线程。他们的格式不兼容bash,但很简单:name=value,没有引用,没有替换。他们还忽略空行和#注释。

我无法让它兼容Postx,但这里有一个应该可以在类似bash的shell中工作(在OSX 10.12.5上的zsh和Ubuntu 14.04上的bash中测试):

while read -r l; do export "$(sed 's/=.*$//' <<<$l)"="$(sed -E 's/^[^=]+=//' <<<$l)"; done < <(grep -E -v '^\s*(#|$)' your-env-file)

不会处理上面链接的文档中示例中的三种情况:

  • bash: export: `123qwe=bar': not a valid identifier
  • bash: export: `org.spring.config=something': not a valid identifier
  • 它不会处理直通语法(一个裸FOO
set -a. ./env.txtset +a

如果env.txt是这样的:

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

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

-a创建或修改的每个变量或函数都被赋予导出属性并标记为导出到后续命令的环境。

使用“+”而不是“-”会导致这些选项被关闭。这些选项也可以在调用shell时使用。当前的选项集可以在$-中找到。

更简单:

  1. 抓取文件内容
  2. 删除任何空行(只是为了防止你分离一些东西)
  3. 删除任何评论(只是以防万一你添加了一些…)
  4. export添加到所有行
  5. eval整件事

eval $(cat .env | sed -e /^$/d -e /^#/d -e 's/^/export /')

另一个选项(您不必运行eval(感谢@JayDeep):

export $(cat .env | sed -e /^$/d -e /^#/d | xargs)

最后,如果你想让你的生活变得简单,把它添加到你的~/.bash_profile

function source_envfile() { export $(cat $1 | sed -e /^$/d -e /^#/d | xargs); }

(确保你重新加载你的巴斯设置!!!source ~/.bash_profile或…只是做一个新的标签/窗口和问题解决)你这样称呼它:source_envfile .env

值中的空白

这里有很多很好的答案,但我发现它们都缺乏对值中空格的支持:

DATABASE_CLIENT_HOST=host db-name db-user 0.0.0.0/0 md5

我找到了2个解决方案,这些解决方案支持空行和注释。

一个基于ses和@javier-buzzi回答

source <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x "&"/g' .env)

和一个基于@john1024回答的循环中的读取线

while read -r line; do declare -x "$line"; done < <(egrep -v "(^#|^\s|^$)" .env)

这里的关键是使用declare -x并将行放在双引号中。我不知道为什么,但是当你将循环代码重新格式化为多行时,它将无法工作-我不是bash程序员,我只是狼吞虎咽地把这些放在一起,它对我来说仍然很神奇:)

我的要求是:

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

完整的工作版本从上面的答案编译:

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

首先,创建一个环境文件,该文件将包含所有环境的键值对,如下所示,并将其命名为您喜欢的任何名称,在我的情况下为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 allexportsource $ENV_FILEset +o allexport
$CMD

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

用途:

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

我在Mac上使用docker-compose和.env文件,并想将.env导入我的bash shell(用于测试),这里的“最佳”答案是在以下变量上绊倒:

. en v

NODE_ARGS=--expose-gc --max_old_space_size=2048

解决方案

所以我最终使用了eval,并用单引号包装了我的env var def。

eval $(grep -v -e '^#' .env | xargs -I {} echo export \'{}\')

bash版本

$ /bin/bash --versionGNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)Copyright (C) 2007 Free Software Foundation, Inc.

我找到的最短路径:

您的.env文件:

VARIABLE_NAME="A_VALUE"

那就

. ./.env && echo ${VARIABLE_NAME}

奖励:因为它是一个简短的一行代码,所以在package.json文件中非常有用

  "scripts": {"echo:variable": ". ./.env && echo ${VARIABLE_NAME}"}

试试这样的东西

for line in `cat your_env_file`; do if [[ $line != \#* ]];then export $line; fi;done

我的. env文件看起来像:

DATABASE_URI="postgres://sa:***@localhost:5432/my_db"VARIABLE_1="SOME_VALUE"VALIABLE_2="123456788"

使用@henke的方式,导出的值最终包含引号"

"postgres://sa:***@localhost:5432/my_db""SOME_VALUE""123456788"

但我希望导出的值只包含:

postgres://sa:***@localhost:5432/my_dbSOME_VALUE123456788

为了修复它,我编辑命令以删除引号:

export $(grep -v '^#' dev.env | tr --delete '"' | xargs -d '\n')
t=$(mktemp) && export -p > "$t" && set -a && . ./.env && set +a && . "$t" && rm "$t" && unset t

它是如何运作的

  1. 创建临时文件。
  2. 将所有当前环境变量值写入临时文件。
  3. 启用将源脚本中所有声明的变量导出到环境。
  4. 读取.env文件。所有变量都将导出到当前环境中。
  5. 禁用将源脚本中所有声明的变量导出到环境。
  6. 读取临时文件的内容。每一行都有declare -x VAR="val",它将每个变量导出到环境中。
  7. 删除临时文件。
  8. 取消设置保存临时文件名的变量。

功能

  • 保留环境中已设置的变量的值
  • .env可以评论
  • .env可以有空行
  • .env不需要像其他答案(set -aset +a)那样的特殊页眉或页脚
  • .env不需要每个值都有export
  • 单行

这是我的变体:

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

与之前的解决方案相比:

  • 它不会将变量泄漏到范围之外(来自.env的值不会暴露给调用者)
  • 不会破坏set选项
  • 返回执行命令的退出代码
  • 使用Postx兼容set -a
  • 使用.而不是source来避免bashism
  • 如果.env加载失败,则不调用命令
with_env rails console

我发现最有效的方法是:

export $(xargs < .env)

补充说明

当我们有这样的.env文件时:

key=valfoo=bar

运行xargs < .env将获得key=val foo=bar

所以我们会得到一个export key=val foo=bar,这正是我们需要的!

限制

  1. 它不处理值中有空格的情况。诸如env之类的命令会产生这种格式。-@Shardj

这个处理RHS上的空格,并跳过“奇怪”的vars,例如bash模块定义(其中包含“()”):

echo "# source this to set env vars" > $bld_dir/.envenv | while read line; dolhs="${line%%=*}"rhs="${line#*=}"if [[ "$lhs" =~ ^[0-9A-Za-z_]+$ ]]; thenecho "export $lhs=\"$rhs\"" >> $bld_dir/.envfidone

不太确定为什么,或者我错过了什么,但是在运行了大部分答案并失败后。我意识到使用这个. env文件:

MY_VAR="hello there!"MY_OTHER_VAR=123

我可以简单地这样做:

source .envecho $MY_VAR

输出:Hello there!

似乎在Ubuntu linux中工作得很好。

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

  • 忽略注释行
  • 在值中允许空格
  • 允许空行
  • 能够在默认为. 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 filesource_env .env.dev       # load custom .env file(source_env && COMMAND)   # run command without saving vars to environment

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

修改自@Dan Kowalczyk

我把这个放在~/.bashrc

set -a. ./.env >/dev/null 2>&1set +a

与Oh-my-Zsh的dotenv插件交叉兼容得很好。(有Oh-my-bash,但它没有dotenv插件。)

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

使用

dotenv_export是一个小型实用程序命令,它读取.env文件并使用ruby#3实现将其转换为export语句。

# first install `dotenv_export`gem install dotenv_export

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

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

我用这个:

source <(cat .env \| sed -E '/^\s*#.*/d' \| tr '\n' '\000' \| sed -z -E 's/^([^=]+)=(.*)/\1\x0\2/g' \| xargs -0 -n2 bash -c 'printf "export %s=%q;\n" "${@}"' /dev/null)

第一次删除评论:

sed -E '/^\s*#.*/d'

然后转换为空分隔符而不是换行符:

tr '\n' '\000'

然后用null替换等于:

sed -z -E 's/^([^=]+)=(.*)/\1\x0\2/g'

然后打印对到有效引用的bash导出(使用bash printf%q):

xargs -0 -n2 bash -c 'printf "export %s=%q;\n" "${@}"' /dev/null

最后,把这一切都归结起来。

它应该适用于几乎所有具有所有特殊字符的情况。

如何保存变量:

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

我如何装载它们

source myvariables.sh

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

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

.env文件示例:

KEY="value with space\nnewline\ttab\tandmultiplelines"

测试:

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

source的问题在于它要求文件具有正确的bash语法,一些特殊字符会破坏它:="'<>等。所以在某些情况下,您可以只

source development.env

它会奏效的。

这个版本,但是,承受每个特殊字符值:

set -asource <(cat development.env | \sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g")set +a

说明:

  • -a意味着每个bash变量都将成为环境变量
  • /^#/d删除注释(以#开头的字符串)
  • /^\s*$/d删除空字符串,包括空格
  • "s/'/'\\\''/g"将每个单引号替换为'\'',这是bash中产生引号的技巧序列:)
  • "s/=\(.*\)/='\1'/g"将每个a=b转换为a='b'

因此,您可以使用特殊字符:)

要调试此代码,请将source替换为cat,您将看到此命令生成的内容。

如果您打算将exec作为脚本的最后一个命令,您可以使用execlineb解释器提供额外的选项。这是脚本的最后一行的样子:

#!/bin/sh...exec envfile -I /etc/default/bla envfile /etc/default/bla-bla my_cmd

envfile ...是来自execline套件的命令,它们依赖于“链加载”。顺便说一句,一旦你进入这个兔子洞,你可能会发现你不再需要shell了(……并重新考虑你的其他生活选择:-)通过使用execlineb解释器而不是完全使用shell,这对于以最小的开销启动服务非常有用,即:

#!/bin/execlineb...envfile -I /etc/default/blaenvfile /etc/default/bla-blamy_cmd

使用shdotenv

dotenv支持符合shell和POSIX的. env语法规范
https://github.com/ko1nksm/shdotenv

eval "$(shdotenv)"

用法

Usage: shdotenv [OPTION]... [--] [COMMAND [ARG]...]
-d, --dialect DIALECT  Specify the .env dialect [default: posix](posix, ruby, node, python, php, go, rust, docker)-s, --shell SHELL      Output in the specified shell format [default: posix](posix, fish)-e, --env ENV_PATH     Location of the .env file [default: .env]Multiple -e options are allowed-o, --overload         Overload predefined environment variables-n, --noexport         Do not export keys without export prefix-g, --grep PATTERN     Output only those that match the regexp pattern-k, --keyonly          Output only variable names-q, --quiet            Suppress all output-v, --version          Show the version and exit-h, --help             Show this message and exit

职位要求:

shdotenv是一个嵌入awk脚本的单一文件外壳脚本。

  • POSIX shell(dash、bash、ksh、zsh等)
  • awk(gawk、nawk、mawk、busybox awk)

我对此的贡献是回答从@的扩展user4040650允许在git存储库中轻松使用。它将尝试从当前目录中获取. env文件,或者如果不存在,则从您所在的git存储库中获取. env文件。如果您已经cd'd到子目录中,然后不必源…/… /.env之类的,这会很有帮助。

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

setenv() {local env_pathif { [ -f .env ] && env_path='.env'; } || { env_path=$(git  rev-parse --show-toplevel 2>/dev/null)/.env && [ -f "$env_path" ]; }; thenecho "sourcing $env_path"set -o allexportsource "$env_path"set +o allexportelseecho "No env file found"fi}

符合POSIX的解决方案(不依赖于bash)

正如其他人所指出的,在这里使用for/这时候循环的问题是shell及其子shell之间不共享变量。然而,我们可以做的是使用args/stdin/stdout在shell之间传递文本。

在子shell中设置环境变量在我们获取脚本时没有帮助

变量不会传播回来-但我们知道我们可以发送文本回来。这段文本也可以是代码,我们可以使用eval在当前shell中评估它。

如果我们生成代码来设置所有的环境变量,然后对结果进行评估呢?

create_exports_script() {echo "$1" | while read line; doecho "export $line"done}
file_contents=$(cat "./conf/myconf.env")eval $(create_exports_script "$file_contents")

bash中的这种函数式元编程可以非常灵活。您也可以通过这种方式生成除了bash/sh之外的其他语言

我的版本:

我打印文件,删除注释行、空行,并从“=”符号中拆分键/值。然后我只应用导出命令。

这种解决方案的优点是文件可以在值中包含特殊字符,如管道、html标签等,并且该值不必像真正的属性文件那样用引号包围。

# Single line versioncat myenvfile.properties | grep -v '^#' | grep '=' | while read line; do IFS=\= read k v <<< $line; export $k="$v"; done
# Mutliline version:cat myenvfile.properties | grep -v '^#' | grep '=' | while read line; doIFS=\= read k v <<< $lineexport $k="$v"done
sh -ac '. conf-file; yourcommand'

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

与较长的版本set -a; . conf-file; set +a; yourcommand不同使用sh可确保导出的值不会永久污染当前环境。它仅为在子shell中运行的程序获取和导出变量。

export的答案。

互动练习

由于互动,您可以尝试内联!

$ mkdir conf && printf 'MINIENTREGA_%s="%s"\n' FECHALIMITE 2011-03-31 FICHEROS \"informe.txt programa.c" DESTINO ./destino/entrega-prac1 >conf/prac1
$ set -- prac1$ while read -r line; do export $line; done <"conf/$1"
bash: export: `programa.c"': not a valid identifier
$ while read -r line; do LANG=C export "$line"; done <"conf/$1"$ echo "$MINIENTREGA_FICHEROS""informe.txt programa.c"

注意双引号!

source别名.

$ set -- prac1$ . "conf/$1"$ echo "$MINIENTREGA_FICHEROS"informe.txt programa.c

好的,那么现在是关于export

export命令告诉shell出口shell变量环境……所以你必须在使用它们之前导出脚本变量子进程(如rubypythonperl甚至另一个shell脚本。

清理以前的操作以进行进一步演示

$ declare +x MINIENTREGA_FECHALIMITE MINIENTREGA_FICHEROS MINIENTREGA_DESTINO$ unset MINIENTREGA_FECHALIMITE MINIENTREGA_FICHEROS MINIENTREGA_DESTINO

因此,从交互式shell中,尝试此操作的最简单方法是运行另一个

$ set -- prac1$ . "conf/$1"$ bash -c 'declare -p MINIENTREGA_FICHEROS'bash: line 1: declare: MINIENTREGA_FICHEROS: not found
$ export MINIENTREGA_FECHALIMITE MINIENTREGA_FICHEROS MINIENTREGA_DESTINO$ bash -c 'declare -p MINIENTREGA_FICHEROS'declare -x MINIENTREGA_FICHEROS="informe.txt programa.c"

用于导出变量的示例包装器

最小包装器,没有安全问题(在采购其他用户可编辑的脚本时要小心!!)。

#!/bin/sh
while IFS== read -r varname _;docase $varname in*[!A-Za-z0-9_]* | '' ) ;;* ) export $varname ;;esacdone <conf/$1. conf/$1
busybox sh -c 'set | grep MINIENTREGA'

prac1作为参数运行,应该产生:

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

在罚款

  • 获取配置文件与声明变量相同。

  • 导出您的变量是指示shell在全局环境中为任何子进程共享他的变量。

这两个操作可以以任何顺序无差别地完成。唯一的要求是两个操作都完成之前您尝试运行任何子进程。

您甚至可以通过导出您的配置文件来一起执行这两个操作,例如:

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

我以基于allexport+source方法的解决方案结束。这里的主要思想是防止覆盖现有变量

function load_env_file() {local FILE_PATH="${1}"local EXISTENT_VARS=$(declare)
set -o allexportsource "${FILE_PATH}"set +o allexport
# errors are supressed as "declare" returns also readonly vars which are not overridableeval "${EXISTENT_VARS}" 2> /dev/null || true}
# Usage example:load_env_file "path/to/.env"
export $(grep -v '^#' envfilename | xargs -L 1  -d '\r' -d '\r\n')

这就像CentOS上的魅力;当你有\r的问题时,它会附加到加载的变量中。它还会处理注释和空白。

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

创建一个像这样的脚本:

# !/bin/shset -o allexportsource $1set +o allexportshiftexec $@

然后像这样使用:

dotenv env-file my-binary

zsh的方法是动态创建一个文件,每行开头都有export,在子shell中获取它,然后执行您的命令:

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

我构建这个脚本来动态地获取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 $filenameecho ''}
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 ]thenecho "A file named '.secret' already exist. Remove it or edit this script."elsepublic_var MY_USER_VARsecret_var MY_PASS_VARfi

它非常容易使用:

# To add var MY_VAR_NAME to the envpublic_var MY_VAR_NAME
# To add var MY_VAR_NAME secretly into the envsecret_var MY_VAR_NAME

例子:

callmarl@LAPTOP ~ % source set_env.shMY_USER_VAR=myusernameMY_PASS_VAR=callmarl@LAPTOP ~ % envMY_USER_VAR=myusernameMY_PASS_VAR=mysecretpass

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