0

My scenario is a little bit complex:

  1. I have an environment variable in my Dockerfile, which is a path: ENV ORACLE_HOME=/home/oracle
  2. I need to do some file manipulation later, so I am using sed
  3. Unfortunately I need to escape the path characters \ for sed before I use the variable.

This is what I have:

ENV ORACLE_HOME=/home/oracle
ENV ORACLE_HOME_ESCAPED="$(printf '%q\n' "$ORACLE_HOME")"
RUN sed 's/.*pattern.*/\"-Dsomekey='${ORACLE_HOME_ESCAPED}'\"/' file

The RUN line works fine if ORACLE_HOME only contains simple characters. My escaping command with printf works properly in bash, but it does not work in Dockerfie.

Unfortunately, I only have GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu) and there is no update for bash 4.4 so I am NOT able to use ${@Q} notation. I use oraclelinux:7-slim as a base image.

Any suggestion about what is wrong with the printf?

zappee
  • 20,148
  • 14
  • 73
  • 129

1 Answers1

1

Any suggestion about what is wrong with the printf?

There's nothing wrong with printf, there is however a problem with how the variables is used.

No ENV does not run a shell that would expand $(...) - ENV is a simple a=b assignment with no expansions.

Try the following and note how quotes are used when expanding the variable, not assigning it:

FROM alpine
ENV ORACLE_HOME="not simple characters?!@#^**^&()"
RUN set -x && \
    printf "%s\n" a pattern b > file && \
    # https://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern
    ORACLE_HOME_ESCAPED_FOR_SED=$(printf '%s\n' "$ORACLE_HOME" | sed -e 's/[\/&]/\\&/g') && \
    sed 's/.*pattern.*/"-Dsomekey='"$ORACLE_HOME_ESCAPED_FOR_SED"'"/' file
# these quotes                     ^                            ^
# prevent word splitting

Results in:

$ docker build .
...
Step 3/3 : RUN set -x &&     printf "%s\n" a pattern b > file &&     ORACLE_HOME_ESCAPED_FOR_SED=$(printf '%s\n' "$ORACLE_HOME" | sed -e 's/[\/&]/\\&/g') &&     sed 's/.*pattern.*/"-Dsomekey='"$ORACLE_HOME_ESCAPED_FOR_SED"'"/' file
 ---> Running in 9a98e726e145
+ printf '%s\n' a pattern b
+ printf '%s\n' 'not simple characters?!@#^**^&()'
+ sed -e 's/[\/&]/\\&/g'
+ ORACLE_HOME_ESCAPED_FOR_SED='not simple characters?!@#^**^\&()'
+ sed 's/.*pattern.*/"-Dsomekey=not simple characters?!@#^**^\&()"/' file
a
"-Dsomekey=not simple characters?!@#^**^&()"
b
Removing intermediate container 9a98e726e145
 ---> 9f9276112bf0
Successfully built 9f9276112bf0

I need to do some file manipulation later, so I am using sed

Depends on the manipulation to be done - in templating cases, envsubst is just enough.

I need to escape the path characters \ for sed before I use the variable.

Yes you do - alternatively use a different s delimiter - s!something!somethingelse!.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111