bash 从键/值对文件设置环境变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19331497/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:18:54  来源:igfitidea点击:

Set environment variables from file of key/value pairs

bashvariablesenvironment-variables

提问by hugo19941994

TL;DR:How do I export a set of key/value pairs from a text file into the shell environment?

TL;DR:如何将一组键/值对从文本文件导出到 shell 环境中?



For the record, below is the original version of the question, with examples.

为了记录,以下是问题的原始版本,并附有示例。

I'm writing a script in bash which parses files with 3 variables in a certain folder, this is one of them:

我正在用 bash 编写一个脚本,它解析某个文件夹中包含 3 个变量的文件,这是其中之一:

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

This file is stored in ./conf/prac1

该文件存储在 ./conf/prac1

My script minientrega.sh then parses the file using this code:

我的脚本 minientrega.sh 然后使用以下代码解析文件:

cat ./conf/ | while read line; do
    export $line
done

But when I execute minientrega.sh prac1in the command line it doesn't set the environment variables

但是当我minientrega.sh prac1在命令行中执行时它没有设置环境变量

I also tried using source ./conf/$1but the same problem still applies

我也尝试使用,source ./conf/$1但同样的问题仍然适用

Maybe there is some other way to do this, I just need to use the environment variables of the file I pass as the argument of my script.

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

采纳答案by anubhava

Problem with your approach is the exportin the whileloop is happening in a sub shell, and those variable will not be available in current shell (parent shell of while loop).

你的方法的问题是exportwhile循环中一个子壳发生,这些变量不会在当前的shell(while循环的父shell)可用。

Add exportcommand in the file itself:

export在文件本身中添加命令:

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

Then you need to source in the file in current shell using:

然后,您需要使用以下命令在当前 shell 中的文件中获取源代码:

. ./conf/prac1

OR

或者

source ./conf/prac1

回答by Silas Paul

This might be helpful:

这可能会有所帮助:

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

Reason why I use this is if I want to test .envstuff in my rails console.

我使用它的原因是我想.env在我的 rails 控制台中测试东西。

gabrielfcame up with a good way to keep the variables local. This solves the potential problem when going from project to project.

gabrielf想出了一个保持变量本地化的好方法。这解决了从项目到项目时的潜在问题。

env $(cat .env | xargs) rails

I've tested this with bash 3.2.51(1)-release

我已经测试过这个 bash 3.2.51(1)-release



Update:

更新:

To ignore lines that start with #, use this (thanks to Pete's comment):

要忽略以 开头的行#,请使用此命令(感谢Pete 的评论):

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

And if you want to unsetall of the variables defined in the file, use this:

如果您想要unset文件中定义的所有变量,请使用以下命令:

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


Update:

更新:

To also handle values with spaces, use:

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

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

on GNU systems -- or:

在 GNU 系统上——或者:

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

on BSD systems.

在 BSD 系统上。

回答by user4040650

-o allexportenables all following variable definitions to be exported. +o allexportdisables this feature.

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

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

回答by Dan Kowalczyk

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

If env.txtis like:

如果env.txt是这样的:

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

Explanation:
-a is equivalent to allexport. In other words, every variable assignment in the shell is exported into the environment (to be used by multiple child processes). Also see this article gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

说明:
-a 等价于 allexport。换句话说,shell 中的每个变量赋值都被导出到环境中(供多个子进程使用)。另请参阅这篇文章 gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

回答by gsf

The allexportoption is mentioned in a couple of other answers here, for which set -ais the shortcut. Sourcing the .env really is better than looping over lines and exporting because it allows for comments, blank lines, and even environment variables generated by commands. My .bashrc includes the following:

allexport此处的其他几个答案中提到了该选项,这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
}

回答by selvan

eval $(cat .env | sed 's/^/export /')

回答by tutuDajuju

Here is another sedsolution, which does not run eval or require ruby:

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

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

This adds export, keeping comments on lines starting with a comment.

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

.env contents

.env 内容

A=1
#B=2

sample run

样品运行

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

I found this especially useful when constructing such a file for loading in a systemd unit file, with EnvironmentFile.

我发现这在构建这样一个文件以加载到systemd 单元文件中EnvironmentFile时特别有用,扩展名为.

回答by Huan

I found the most efficient way is:

我发现最有效的方法是:

export $(xargs < .env)

Explanation

解释

When we have a .envfile like this:

当我们有这样的.env文件时:

key=val
foo=bar

run xargs < .envwill get key=val foo=bar

运行xargs < .env会得到key=val foo=bar

so we will get an export key=val foo=barand it's exactly what we need!

所以我们会得到一个export key=val foo=bar,这正是我们所需要的!

Limitation

局限性

  1. It doesn't handle cases where the values have spaces in them. Commands such as env produce this format. – @Shardj
  1. 它不处理值中有空格的情况。诸如 env 之类的命令会产生这种格式。– @Shardj

回答by Nagev

I have upvoted user4040650's answer because it's both simple, and it allows comments in the file (i.e. lines starting with #), which is highly desirable for me, as comments explaining the variables can be added. Just rewriting in the context of the original question.

我赞成 user4040650 的答案,因为它既简单又允许在文件中添加注释(即以 # 开头的行),这对我来说非常理想,因为可以添加解释变量的注释。只是在原始问题的上下文中重写。

If the script is callled as indicated: minientrega.sh prac1, then minientrega.sh could have:

如果脚本按指示minientrega.sh prac1调用:,则 minientrega.sh 可能具有:

set -a # export all variables created next
source 
set +a # stop exporting

# test that it works
echo "Ficheros: $MINIENTREGA_FICHEROS"

The following was extracted from the set documentation:

以下内容摘自set 文档

This builtin is so complicated that it deserves its own section. set allows you to change the values of shell options and set the positional parameters, or to display the names and values of shell variables.

set [--abefhkmnptuvxBCEHPT] [-o option-name] [argument …] set [+abefhkmnptuvxBCEHPT] [+o option-name] [argument …]

If no options or arguments are supplied, set displays the names and values of all shell variables and functions, sorted according to the current locale, in a format that may be reused as input for setting or resetting the currently-set variables. Read-only variables cannot be reset. In POSIX mode, only shell variables are listed.

When options are supplied, they set or unset shell attributes. Options, if specified, have the following meanings:

-a Each variable or function that is created or modified is given the export attribute and marked for export to the environment of subsequent commands.

这个内置函数非常复杂,值得拥有它自己的部分。set 允许您更改 shell 选项的值和设置位置参数,或显示 shell 变量的名称和值。

set [--abefhkmnptuvxBCEHPT] [-o option-name] [argument ...] set [+abefhkmnptuvxBCEHPT] [+o option-name] [argument ...]

如果未提供选项或参数,则 set 显示所有 shell 变量和函数的名称和值,根据当前语言环境排序,格式可重复用作设置或重置当前设置的变量的输入。只读变量无法重置。在 POSIX 模式下,只列出 shell 变量。

提供选项时,它们会设置或取消设置 shell 属性。选项(如果指定)具有以下含义:

-a 创建或修改的每个变量或函数都被赋予导出属性并标记为导出到后续命令的环境。

And this as well:

这也是:

Using ‘+' rather than ‘-' causes these options to be turned off. The options can also be used upon invocation of the shell. The current set of options may be found in $-.

使用“+”而不是“-”会导致这些选项被关闭。这些选项也可以在调用 shell 时使用。当前的选项集可以在 $- 中找到。

回答by Jaydeep Solanki

Improving on Silas Paul's answer

改进 Silas Paul 的回答

exporting the variables on a subshell makes them local to the command.

在子shell上导出变量使它们在命令中是本地的。

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

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