【问题标题】:Docker - dynamic regex-based sed substitution in filesDocker - 文件中基于正则表达式的动态 sed 替换
【发布时间】:2017-05-10 17:52:13
【问题描述】:

我在 env_file 中声明了各种环境变量,并在 docker-compose.yml 中引用

  • export FOO=bar

  • export FAZ=baz

在容器内的配置文件中,我这样引用这些环境变量:

  • Today is a great day to ${FOO} and ${FAZ}

我希望能够捕获以${ 开头并以} 结尾的所有文本实例(例如${<SOMETHING>}),然后将其替换为键<SOMETHING> 的环境变量。

以下内容在 shell 中有效,但我无法将其与 sed -i 一起用于文件或 bash 脚本中。

echo "TODAY IS ${DAY}" | sed -r 's/(<foobar>\$[\w{}]+)/<foobar>/g

  • 如果环境变量DAY 是“FUNDAY”,则会产生:"TODAY IS FUNDAY"

【问题讨论】:

  • 您好,我正在检查您的问题,但不是很清楚。 “希望能够捕获所有以 ${ 开头并以 } 结尾的文本实例(例如 ${}),然后将其替换为键 的环境变量。”是什么意思?你能详细说明一下吗?
  • 如果 conf 包含 ${Foobar},如果键相同,我会尝试将其替换为环境变量。 Today is ${DAY} --> 如果带有键 DAY 的变量的值为 Funday,则为“今天是今天”。最终,这是为了避免手动映射每个变量。
  • 我已投票删除我的答案,因为我意识到这完全是题外话,对您的事业没有帮助。我刚刚了解了您的问题,我将介绍一些您可能会觉得有用的东西。
  • 感谢@UselessPerson - 我意识到这是一个非常晦涩难懂的问题,并且我正在尝试使用一种相当通用的方法。

标签: bash docker sed docker-compose


【解决方案1】:

我想我发现了一些你可能感兴趣的东西。请注意,它只使用 sed、就地编辑和 bash。在我们开始之前,让我们看看输入和输出:

环境文件/变量:如下所示,我们的文件"myenv"有3个变量,它们的值如下所示。

%_Host@User> file myenv
myenv: ASCII text
%_Host@User> cat myenv
export FOO='This is FOO'
export BAR='This is BAR'
export BAZ='This is BAZ'
%_Host@User> env|egrep "FOO|BAR|BAZ"
FOO=This is FOO
BAR=This is BAR
BAZ=This is BAZ
%_Host@User>

执行操作的目标文件:我们的目标是读取文件sample.txt,如果在加载的环境文件中找到变量的值,则将其替换为实际值。我们的第 4 行没有在我们的变量文件中定义,所以它应该保持不变。

%_Host@User> cat sample.txt
${FOO} is TRUE
${BAR} is TRUE
${BAZ} is TRUE
${BRAZ} is TRUE
%_Host@User>

SCRIPT 结果和最终输出: 为了演示,我正在打印从目标文件sample.txt 读取的行。如果容器内的变量(例如:${FOO} 在任何一行中找到,我们将其替换为它的值(例如:This is FOO 在这种情况下),我们可以从 env 获取

%_Host@User> ./env.sh sample.txt ; cat sample.txt
[1.] Line is: [${FOO} is TRUE]
[1.] VAR:[FOO] has VALUE:[This is FOO]

[2.] Line is: [${BAR} is TRUE]
[2.] VAR:[BAR] has VALUE:[This is BAR]

[3.] Line is: [${BAZ} is TRUE]
[3.] VAR:[BAZ] has VALUE:[This is BAZ]

[4.] Line is: [${BRAZ} is TRUE]
[4.] VAR:[BRAZ] not found and NO CHANGE IN FILE !!

This is FOO is TRUE
This is BAR is TRUE
This is BAZ is TRUE
${BRAZ} is TRUE
%_Host@User>

如上所示,我们已经成功地将${FOO} 更改为This is FOO,并保持任何其他/s(不在我们的env 文件中)不变。

SCRIPT 及其工作原理:

#!/bin/bash

i=1

cfgfile="$1"

cat $cfgfile | while read line

do
        echo "[${i}.] Line is: [$line]"

        var=$(echo $line | sed 's#^.*\${\(\w*\)}.*$#\1#g')
        val=$(env |grep "$var"| cut -f2 -d"=")

        env|grep "${var}=" >/dev/null

        if [ $? -eq 0 ]
        then
                echo "[$i.] VAR:[$var] has VALUE:[$val]"

                # Perform  inplace editing.
                sed -i "s@\${$var}@$val@g" "$cfgfile"
        else
                echo "[$i.] VAR:[$var] not found and NO CHANGE IN FILE !!"
        fi

        ((i++)) ; echo
done

以上脚本遵循以下步骤:

  1. i=1 只是我们的柜台。没那么重要。仅用于演示目的。
  2. cfgfile="$1" 接受来自提示的文件。
  3. 我们 cat 文件并在 while 循环中逐行读取。
  4. 我们回显该行,然后从${FOO} 中提取FOO,并从环境中提取其实际值,即This is FOO,并将其存储在varval 中。很简单。
  5. 我们测试这个变量FOO是否在env中定义并检查命令状态。
  6. 如果已定义,即 $?0True,我们将继续执行就地编辑,否则我们将不做任何更改。

我认为您应该尝试使用双引号 (") 而不是单引号 (') 的原始命令。它应该可以工作。

如果这有用,请告诉我们。

干杯。

【讨论】:

  • 谢谢 - 感激不尽。我将对此进行测试并标记答案是否成功。但是,无论如何,我已经转向使用envsubst。不过,这对于未来的 bash 脚本编写来说是件好事。
  • 如果您遇到任何问题或想要修改某些内容,请告诉我。我是来解决这个问题的,因为它还没有答案。干杯!
猜你喜欢
  • 2018-08-22
  • 1970-01-01
  • 2020-10-16
  • 2021-12-31
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
  • 2013-08-25
相关资源
最近更新 更多