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

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


当前回答

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

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

$

其他回答

在这里的几个其他答案中提到了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
}

我用这个:

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替换equal:

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

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

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

最后是来源。

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

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

.env

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

解决方案

所以我最终使用eval,并将env var defs包装在单引号中。

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

Bash的版本

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

SAVE=$(set +o | grep allexport) && set -o allexport && ..环境;评估“$SAVE”

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

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

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

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

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