¿Cómo evitar heredoc expandir variables?

Intento crear un archivo de script utilizando una cadena de sustitución de ENV pero también quiero evitar que algunos escapen

export PLACEHOLDER1="myPlaceholder1Value" export PLACEHOLDER2="myPlaceholder2Value" sudo /bin/su -c "cat < /etc/init.d/my-script #!/bin/bash # ### BEGIN INIT INFO # Provides: my-script # Required-Start: \$remote_fs \$syslog # Required-Stop: \$remote_fs \$syslog # Should-Start: \$network \$time # Should-Stop: \$network \$time # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: blabla # Description: bla bla desc # ### END INIT INFO # myvariable_1=toto$PLACEHOLDER1 myvariable_2=titi$PLACEHOLDER2 myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\" EOF " 

Resulta que no es bueno ya que myvariable_final no se escapa y se sustituye como el de las dependencias de script de inicio ($ remote_fs, $ syslog, $ network, $ time)

 #!/bin/bash # ### BEGIN INIT INFO # Provides: my-script # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: blabla # Description: bla bla desc # ### END INIT INFO # myvariable_1=totomyPlaceholder1Value myvariable_2=titimyPlaceholder2Value myvariable_final="dynamicvar=," 

Si trato de poner una barra invertida \ detrás de los dólares $ , logro evitar la sustitución pero obtengo una barra invertida no deseada \ :

 export PLACEHOLDER1="myPlaceholder1Value" export PLACEHOLDER2="myPlaceholder2Value" sudo /bin/su -c "cat < /etc/init.d/my-script #!/bin/bash # ### BEGIN INIT INFO # Provides: my-script # Required-Start: \$\remote_fs \$\syslog # Required-Stop: \$remote_fs \$syslog # Should-Start: \$network \$time # Should-Stop: \$network \$time # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: blabla # Description: bla bla desc # ### END INIT INFO # myvariable_1=toto$PLACEHOLDER1 myvariable_2=titi$PLACEHOLDER2 myvariable_final=\"dynamicvar=\$\{myvariable_1},\$\{myvariable_2}\" EOF " 

resultados en:

 #!/bin/bash # ### BEGIN INIT INFO # Provides: my-script # Required-Start: $\remote_fs $\syslog # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: blabla # Description: bla bla desc # ### END INIT INFO # myvariable_1=totomyPlaceholder1Value myvariable_2=titimyPlaceholder2Value myvariable_final="dynamicvar=$\{myvariable_1},$\{myvariable_2}" 

Resultado buscado / atendido que debería haber sido:

 #!/bin/bash # ### BEGIN INIT INFO # Provides: my-script # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Should-Start: $network $time # Should-Stop: $network $time # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: blabla # Description: bla bla desc # ### END INIT INFO # myvariable_1=totomyPlaceholder1Value myvariable_2=titimyPlaceholder2Value myvariable_final="dynamicvar=${myvariable_1},${myvariable_2}" 

resuelto poniendo una cotización alrededor del EOF como se muestra a continuación y usando la barra invertida para controlar el escape cuando sea necesario

 export PLACEHOLDER1="myPlaceholder1Value" export PLACEHOLDER2="myPlaceholder2Value" sudo /bin/su -c "cat < /etc/init.d/my-script #!/bin/bash # ### BEGIN INIT INFO # Provides: my-script # Required-Start: \$remote_fs \$syslog # Required-Stop: \$remote_fs \$syslog # Should-Start: \$network \$time # Should-Stop: \$network \$time # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: blabla # Description: bla bla desc # ### END INIT INFO # myvariable_1=toto$PLACEHOLDER1 myvariable_2=titi$PLACEHOLDER2 myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\" EOF " 

Simplemente use 'EOF' para evitar que la variable se expanda:

 sudo /bin/su -c "cat << 'EOF' > /etc/init.d/my-script # ^ ^ 

De man bash :

Aquí documentos

Este tipo de redirección ordena al shell que lea la entrada de la fuente actual hasta que se vea una línea que solo contenga un delimitador (sin espacios en blanco al final). Todas las líneas leídas hasta ese punto se usan luego como entrada estándar para un comando.

El formato de los documentos aquí es:

  <<[-]word here-document delimiter 

No se realiza expansión de parámetros, sustitución de comandos, expansión aritmética o expansión de nombre de ruta en palabra. Si se citan los caracteres de la palabra, el delimitador es el resultado de la eliminación de la cita en la palabra, y las líneas en el documento aquí no se expanden. Si la palabra no está citada, todas las líneas del documento aquí están sujetas a expansión de parámetros, sustitución de comandos y expansión aritmética . En este último caso, la secuencia de caracteres \ se ignora, y \ se debe usar para citar los caracteres \, $ y `.

al usar el comando su, coloca el comando en sigle quotes y simplemente escapa del $ con una barra invertida. las variables de marcador de posición tienen que establecerse en el contexto de comando bash (aquí después de su). así que tienes que hacer algo como

 su -c 'ph="ph"; cat << EOF > script varinscript=$ph var=\${var} EOF'