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

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


当前回答

下面是另一个sed解决方案,它不运行eval或需要ruby:

source <(sed -E -n 's/[^#]+/export &/ p' ~/.env)

这添加了导出,将注释保留在以注释开头的行中。

.env内容

A=1
#B=2

样本运行

$ sed -E -n 's/[^#]+/export &/ p' ~/.env
export A=1
#export B=2

我发现这在用EnvironmentFile构造这样一个文件加载到systemd单元文件时特别有用。

其他回答

你可以使用你的原始脚本来设置变量,但你需要以以下方式调用它(独立的点):

. ./minientrega.sh

此外,在读取方法时,cat |可能会出现问题。我建议在读行时使用这种方法;做……done < $FILE。

下面是一个工作示例:

> cat test.conf
VARIABLE_TMP1=some_value

> cat run_test.sh
#/bin/bash
while read line; do export "$line";
done < test.conf
echo "done"

> . ./run_test.sh
done

> echo $VARIABLE_TMP1
some_value

这可能会有帮助:

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

我使用这个的原因是如果我想在我的rails控制台中测试。env的东西。

Gabrielf想出了一个保持变量局部的好方法。这解决了从一个项目到另一个项目时的潜在问题。

env $(cat .env | xargs) rails

我已经用bash 3.2.51(1)-release测试了这一点


更新:

要忽略以#开头的行,使用这个(感谢Pete的评论):

export $(grep -v '^#' .env | xargs)

如果你想取消文件中定义的所有变量,使用这个:

unset $(grep -v '^#' .env | sed -E 's/(.*)=.*/\1/' | xargs)

更新:

要处理带有空格的值,请使用:

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

在GNU系统上——或者:

export $(grep -v '^#' .env | xargs -0)

在BSD系统上。


从这个答案中,你可以自动检测操作系统:

export-env.sh

#!/bin/sh

## Usage:
##   . ./export-env.sh ; $COMMAND
##   . ./export-env.sh ; echo ${MINIENTREGA_FECHALIMITE}

unamestr=$(uname)
if [ "$unamestr" = 'Linux' ]; then

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

elif [ "$unamestr" = 'FreeBSD' ] || [ "$unamestr" = 'Darwin' ]; then

  export $(grep -v '^#' .env | xargs -0)

fi

首先,创建一个环境文件,其中包含如下所示环境的所有键-值对,并将其命名为任何您喜欢的名称,在我的示例中为env_var.env

MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.c"
MINIENTREGA_DESTINO="./destino/entrega-prac1"

然后创建一个脚本,该脚本将导出python环境的所有环境变量,如下所示,并将其命名为export_env.sh

#!/usr/bin/env bash

ENV_FILE="$1"
CMD=${@:2}

set -o allexport
source $ENV_FILE
set +o allexport

$CMD

该脚本将第一个参数作为环境文件,然后导出该文件中的所有环境变量,然后在此之后运行该命令。

用法:

./export_env.sh env_var.env python app.py

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

使用shdotenv

dotenv支持shell和posix兼容的.env语法规范 https://github.com/ko1nksm/shdotenv

eval "$(shdotenv)"

使用

Usage: shdotenv [OPTION]... [--] [COMMAND [ARG]...]

  -d, --dialect DIALECT  Specify the .env dialect [default: posix]
                           (posix, ruby, node, python, php, go, rust, docker)
  -s, --shell SHELL      Output in the specified shell format [default: posix]
                           (posix, fish)
  -e, --env ENV_PATH     Location of the .env file [default: .env]
                           Multiple -e options are allowed
  -o, --overload         Overload predefined environment variables
  -n, --noexport         Do not export keys without export prefix
  -g, --grep PATTERN     Output only those that match the regexp pattern
  -k, --keyonly          Output only variable names
  -q, --quiet            Suppress all output
  -v, --version          Show the version and exit
  -h, --help             Show this message and exit

需求

Shdotenv是一个内置awk脚本的单文件shell脚本。

POSIX shell (dash, bash, ksh, zsh, etc) awk (gawk, nawk, mawk, busybox awk)