Issue
My scenario is a little bit complex:
- I have an environment variable in my
Dockerfile
, which is a path:ENV ORACLE_HOME=/home/oracle
- I need to do some file manipulation later, so I am using sed
- 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
?
Solution
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!
.
Answered By - KamilCuk