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

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


当前回答

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

@anubhava的解决方案使得编写bash友好的配置文件非常烦人,而且-你可能不想总是导出你的配置。 @Silas Paul解决方案中断时,你的变量有空格或其他字符,在引号值中工作得很好,但$()使混乱。

以下是我的解决方案,在我看来仍然很糟糕——并且不能解决Silas提出的“只导出到一个孩子”的问题(尽管你可能可以在子shell中运行它来限制范围):

source .conf-file
export $(cut -d= -f1 < .conf-file)

其他回答

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

source development.env

它会起作用的。

然而,这个版本可以承受值中的所有特殊字符:

set -a
source <(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,您将看到该命令产生的结果。

我的看法是:

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

这种解决方案的优点是文件可以在值中包含特殊字符,如管道、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

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

例子:

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

参见:

http://tldp.org/LDP/abs/html/internalvariables.html#IFSREF https://unix.stackexchange.com/a/196761

我的.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_db
SOME_VALUE
123456788

为了解决这个问题,我编辑命令删除引号:

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

不知道为什么,或者我错过了什么,但在经历了大部分答案和失败之后。我意识到通过这个。env文件:

MY_VAR="hello there!"
MY_OTHER_VAR=123

我可以简单地这样做:

source .env
echo $MY_VAR

输出:你好!

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