如何在本地获取我在Docker格式的env文件中定义的环境变量?

时间:2018-03-20 23:30:18

标签: bash docker

我用Docker格式编写了一堆环境变量,但现在我想在该上下文之外使用它们。我怎样才能用一行bash来源它们?

详细

Docker runcompose具有从文件导入一组环境变量的便利工具。该文件具有非常直观的格式。

  1.   

    该值按原样使用,根本不进行修改。例如,如果值被引号括起来(通常是shell变量的情况),则引号包含在传递的值中

  2.   

    以#开头的行被视为注释并被忽略

  3.   

    空行也被忽略。

  4. "如果没有提供=且该变量是......在您的本地环境中导出," docker"将它传递给容器"
  5. 值得庆幸的是,=之前的空格会导致运行失败
  6. 所以,例如,这个env文件:

    # This is a comment, with an = sign, just to mess with us
    VAR1=value1
    VAR2=value2
    
    USER
    VAR3=is going to = trouble
    VAR4=this $sign will mess with things
    VAR5=var # with what looks like a comment
    #VAR7 =would fail
    VAR8= but what about this?
    VAR9="and this?"
    

    在容器中产生这些env变量:

    user=ubuntu
    VAR1=value1
    VAR2=value2
    VAR3=is going to = trouble
    VAR4=this $sign will mess with things
    VAR5=var # with what looks like a comment
    VAR8= but what about this?
    VAR9="and this?"
    

    光明的一面是,一旦我知道我在做什么,就可以很容易地预测到这种效果。我所看到的就是我得到的。但我不认为bash能够以相同的方式解释这一点,而无需进行大量更改。如何将这个方形Docker挂钉放入圆形Bash孔中?

1 个答案:

答案 0 :(得分:2)

TL; DR:

source <(sed -E -e "s/^([^#])/export \1/" -e "s/=/='/" -e "s/(=.*)$/\1'/" env.list)

您可能希望source一个文件,其内容为

  执行

就像在命令行打印一样。

但是什么档案?原始docker env文件是不合适的,因为它不会export分配的变量,以便子进程可以使用它们,并且任何带有空格,引号和其他特殊字符的输入行都会有不合需要的结果

由于您不想手动编辑文件,因此可以使用流编辑器将线条转换为更易于使用bash的内容。我开始尝试使用一个或两个复杂的Perl 5正则表达式或某些工具组合来解决这个问题,但我最终使用一个简单和两个扩展正则表达式确定了一个sed命令:

sed -E -e "s/^([^#])/export \1/" -e "s/=/='/" -e "s/(=.*)$/\1'/" env.list

这很有用。

  • 第一个表达式将export添加到第一个字符不是#的任何行。
    • 如上所述,这使变量可用于您在此会话中运行的任何其他内容,您的整个目标就在这里。
  • 第二个表达式只是在第一行=之后插入单引号(如果适用)。
    • 这将始终包含整个值,而贪婪的匹配可能会丢掉一些(例如)VAR3,例如
  • 第三个表达式将第二个引号附加到至少有一个=的任何行。
    • 此处重要的是要再次匹配=,以便我们不会创建无与伦比的引号

结果:

# This is a comment, with an =' sign, just to mess with us'
export VAR1='value1'
export VAR2='value2'

export USER
export VAR3='is going to = trouble'
export VAR4='this $sign will mess with things'
export VAR5='var # with what looks like a comment'
#VAR7 ='would fail'
export VAR8=' but what about this?'
export VAR9='"and this?"'

更多细节:

  • 通过将值包装在单引号中,您就可以了
    • 阻止bash假设空格后的单词是命令
    • 适当地将#和所有后续字符带入VAR5
    • 阻止了$sign的评估,如果用双引号括起来,bash会被解释为变量

最后,我们将利用process substitution将此流作为文件传递给source,将所有这些内容归结为一行bash。

source <(sed -E -e "s/^([^#])/export \1/" -e "s/=/='/" -e "s/(=.*)$/\1'/" env.list)

Etvoilà!