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

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


当前回答

我的看法是:

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

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

# Single line version
cat 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; do 
  IFS=\= read k v <<< $line
  export $k="$v"
done

其他回答

我的.env:

#!/bin/bash
set -a # export all variables

#comments as usual, this is a bash script
USER=foo
PASS=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

这是我的变种:

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

与之前方案相比:

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

with_env rails console

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

我不能完全让它与posix兼容,但这里有一个应该在bash-like 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':不是有效的标识符 Bash: export: `org.spring。Config =something':不是有效的标识符 并且它不会处理传递语法(一个纯FOO)

如果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"'

试试这样的方法

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