snakesNbronies
snakesNbronies

Reputation: 3920

Docker - dynamic regex-based sed substitution in files

I have various environment variables declared inside an env_file referenced in a docker-compose.yml

In a config file within a container I reference these environment variables as such:

I want to be able to capture all instances of text start with ${ and ending with } (ex. ${<SOMETHING>}) and then replace it with the environment variable of key <SOMETHING>.

The following works in the shell, but I cannot get this to work with sed -i against a file, or within a bash script.

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

Upvotes: 1

Views: 1676

Answers (1)

User9102d82
User9102d82

Reputation: 1190

I think i found something which may interest you. Please note that it complies to using only sed, in place editing and bash. Before we get into it, lets see the input and output:

Environment file/variables: As seen below, our file "myenv" has 3 variables and their values are as seen below.

%_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>

Target file to perform the operation upon: Our target is to read the file sample.txt and replace values of variables with their actual values, if they are found in the loaded environment file. Our 4th line is not defined in our variable file so it should be untouched or unchanged.

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

SCRIPT Result and final output: To demonstrate, I am printing the lines as they are read from the target file sample.txt. If the variable inside the container (eg: ${FOO} is found in any of the line, we replace the it with its value (eg: This is FOO in this case) which we can obtain from the 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>

As seen above, we have managed to change the ${FOO} with This is FOO as expected and left any other/s (which were not in our env file) untouched.

SCRIPT and its working:

#!/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

Above script is following these steps:

  1. i=1 is just our counter. Not so important. Only for demo purpose.
  2. cfgfile="$1" to accept file from prompt.
  3. We cat the file and read it line by line in a while loop.
  4. We echo the line and then extract FOO from ${FOO} and its actual value from env i.e. This is FOO and store it in var and val. simple enough.
  5. We test whether this variable FOO is defined in env or not and check for command status.
  6. If it is defined i.e. $? is 0 or True, we go ahead and perform in place editing or else we leave the line alone and no change.

I believe you should try your original command with double quotes (") instead of single ('). It should work.

Please let us know if this was any useful.

Cheers.

Upvotes: 1

Related Questions