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

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


当前回答

简单:

获取文件的内容 删除任何空行(以防你分开一些东西) 删除任何注释(以防你添加了一些…) 将export添加到所有行 对整个事件进行评估

eval (cat .env美元| sed - e / ^ $ / d - e / ^ # / d - e ' s / ^ /出口/ ')

另一个选择(你不必运行eval(感谢@Jaydeep)):

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

最后,如果你想让你的生活真的很简单,把这个添加到你的~/.bash_profile:

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

(请务必重新加载bash设置!!~ /来源。bash_profile或. .只要新建一个标签/窗口,问题就解决了),你这样叫它:source_envfile .env

其他回答

我的.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

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

改进塞拉斯·保罗的回答

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

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

如果您想让exec作为脚本的最后一个命令,那么您可以使用execlineb解释器。这是脚本的最后一行:

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

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

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

我的看法是:

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

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