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

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


当前回答

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

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

其他回答

很抱歉要补充另一个答案,但因为它很简单,在很多情况下都有效,尝试一下:

export $(< ~/my/.env)

这个函数处理RHS上的空格,并跳过'奇怪的'变量,例如bash模块定义(其中有'()'):

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

我用这个:

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

最后是来源。

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

set -a
. ./env.txt
set +a

如果env.txt像这样:

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

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

-a每个创建或修改的变量或函数都被赋予export属性,并标记为可导出到后续命令的环境。 使用“+”而不是“-”会关闭这些选项。还可以在调用shell时使用这些选项。当前选项集可以在$-中找到。

如何保存变量:

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

如何装载它们

source myvariables.sh