如何从文件中导出变量?

Nee*_*rav 138 bash

我有一个tmp.txt包含要导出的变量的文件,例如:

a=123
b="hello world"
c="one more variable"
Run Code Online (Sandbox Code Playgroud)

如何使用export命令导出所有这些变量,以便子进程以后可以使用它们?

Sté*_*las 279

set -a
. ./tmp.txt
set +a
Run Code Online (Sandbox Code Playgroud)

set -a导致从现在开始定义的变量¹被自动导出。它可以在任何类似 Bourne 的 shell 中使用。.source命令的标准名称和 Bourne 名称,所以我更喜欢它的可移植性(source来自csh并且现在在大多数现代 Bourne-like shell 中可用,包括bash虽然(有时行为略有不同))。

在 POSIX shell 中,您还可以使用set -o allexport更具描述性的替代方式来编写它(set +o allexport取消设置)。

您可以通过以下方式使其成为一个函数:

export_from() {
  # local is not a standard command but is pretty common. It's needed here
  # for this code to be re-entrant (for the case where sourced files to
  # call export_from). We still use _export_from_ prefix to namespace
  # those variables to reduce the risk of those variables being some of
  # those exported by the sourced file.
  local _export_from_ret _export_from_restore _export_from_file

  _export_from_ret=0

  # record current state of the allexport option. Some shells (ksh93/zsh)
  # have support for local scope for options, but there's no standard
  # equivalent.
  case $- in
    (*a*) _export_from_restore=;;
    (*)   _export_from_restore='set +a';;
  esac

  for _export_from_file do
    # using the command prefix removes the "special" attribute of the "."
    # command so that it doesn't exit the shell when failing.
    command . "$_export_from_file" || _export_from_ret="$?"
  done
  eval "$_export_from_restore"
  return "$_export_from_ret"
}
Run Code Online (Sandbox Code Playgroud)

¹ 在 中bash,请注意它还会导致所有在打开时声明的函数allexport都导出到环境中(作为BASH_FUNC_myfunction%%环境变量,然后由bash在该环境中运行的所有shell导入,即使在作为 运行时sh)。

  • 通过 set,-<char> 将其打开,+<char> 将其关闭。 (2认同)

gle*_*man 107

source tmp.txt
export a b c
./child ...
Run Code Online (Sandbox Code Playgroud)

从您的其他问题来看,您不想对变量名称进行硬编码:

source tmp.txt
export $(cut -d= -f1 tmp.txt)
Run Code Online (Sandbox Code Playgroud)

测试一下:

$ source tmp.txt
$ echo "$a $b $c"
123 hello world one more variable
$ perl -E 'say "@ENV{qw(a b c)}"'

$ export $(cut -d= -f1 tmp.txt)
$ perl -E 'say "@ENV{qw(a b c)}"'
123 hello world one more variable
Run Code Online (Sandbox Code Playgroud)

  • @ChrisLamb 您可以使用 `grep` 跳过评论:`export $(grep --regexp ^[AZ] tmp.txt | cut -d= -f1)` (8认同)
  • 例如,如果环境文件包含注释,这将不起作用。(例如,可以被 systemd 的 EnvironmentFile 重用的文件) (4认同)
  • 单行版本忽略 .env 文件中的注释`source .env && export $(sed '/^#/d' .env | cut -d= -f1)` (2认同)

vil*_*asv 7

一种不需要来源的危险单线:

export $(xargs <file)
Run Code Online (Sandbox Code Playgroud)
  • 不能处理注释,经常用在环境文件中
  • 它不能处理带有空格的值,就像在问题示例中一样
  • 如果它们偶然匹配,它可能会无意中将 glob 模式扩展到文件中

这有点危险,因为它通过 bash 扩展传递行,但是当我知道我有安全的环境文件时,它对我很有用。

  • 您应该在问题中给出的示例中尝试这样做。您会注意到由于 shell 在空格上进行的拆分,您得到了错误的值。 (2认同)
  • 此外,如果您不走运,一行可能包含会拉入文件名的文件名通配符。 (2认同)
  • “xargs 什么都没有?_为什么_这有效?” 我想知道。xargs 手册页回答:“如果省略 **utility**,则使用 echo(1)” (2认同)

小智 5

做就是了:

while read LINE; do export "$LINE"; done < ./tmp.txt
Run Code Online (Sandbox Code Playgroud)

  • 这是易碎的。它不允许在输入文件中添加注释,无法正确处理带引号的变量值,并且在处理多行变量时会失败。当然,我没有很多多行变量,但我确实经常使用注释,并且经常需要对变量值使用引号。 (4认同)