Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid heredoc expanding variables? [duplicate]

I'm trying to create a script file using substitution string from ENV but want also to prevent some from escaping

export PLACEHOLDER1="myPlaceholder1Value" sudo /bin/su -c "cat << EOF > /etc/init.d/my-script #!/bin/bash  myvariable_1=toto$PLACEHOLDER1 myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\" EOF " 

It results in which is not good as the myvariable_final are not escaped and substituted as the one from the init script dependencies ($remote_fs, $syslog, $network, $time)

#!/bin/bash  myvariable_1=totomyPlaceholder1Value myvariable_2=titimyPlaceholder2Value myvariable_final="dynamicvar=," 

If i try to put a backslash \ behind the dollars $, I manage to avoid the substitution but I getting an unwanted backslash \:

export PLACEHOLDER1="myPlaceholder1Value" export PLACEHOLDER2="myPlaceholder2Value" sudo /bin/su -c "cat << EOF > /etc/init.d/my-script #!/bin/bash  myvariable_1=toto$PLACEHOLDER1 myvariable_2=titi$PLACEHOLDER2 myvariable_final=\"dynamicvar=\$\{myvariable_1},\$\{myvariable_2}\" EOF " 

results in:

#!/bin/bash  myvariable_1=totomyPlaceholder1Value myvariable_2=titimyPlaceholder2Value myvariable_final="dynamicvar=$\{myvariable_1},$\{myvariable_2}" 

Wanted/attended result whould have been :

#!/bin/bash  myvariable_1=totomyPlaceholder1Value myvariable_2=titimyPlaceholder2Value myvariable_final="dynamicvar=${myvariable_1},${myvariable_2}" 

solved by putting quote around the EOF as below and using backslash to control the escaping when needed

export PLACEHOLDER1="myPlaceholder1Value" export PLACEHOLDER2="myPlaceholder2Value" sudo /bin/su -c "cat << 'EOF' > /etc/init.d/my-script #!/bin/bash  myvariable_1=toto$PLACEHOLDER1 myvariable_2=titi$PLACEHOLDER2 myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\" EOF " 
like image 727
TheCodeKiller Avatar asked Jan 13 '15 11:01

TheCodeKiller


People also ask

How do I end HereDoc?

To use here-document in any bash script, you have to use the symbol << followed by any delimiting identifier after any bash command and close the HereDoc by using the same delimiting identifier at the end of the text.

What is HereDoc delimiter?

Heredoc uses 2 angle brackets (<<) followed by a delimiter token. The same delimiter token will be used to terminate the block of code. Whatever comes within the delimiter is considered to be a block of code.

Which symbol is used for creating HereDoc?

The most common syntax for here documents, originating in Unix shells, is << followed by a delimiting identifier (often the word EOF or END), followed, starting on the next line, by the text to be quoted, and then closed by the same delimiting identifier on its own line.


2 Answers

Just use 'EOF' to prevent the variable from expanding:

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

From man bash:

Here Documents

This type of redirection instructs the shell to read input from the current source until a line containing only delimiter (with no trailing blanks) is seen. All of the lines read up to that point are then used as the standard input for a command.

The format of here-documents is:

      <<[-]word               here-document       delimiter 

No parameter expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. In the latter case, the character sequence \<newline> is ignored, and \ must be used to quote the characters \, $, and `.

like image 182
fedorqui 'SO stop harming' Avatar answered Sep 29 '22 02:09

fedorqui 'SO stop harming'


when using the su command put the command itself in sigle quotes and just escape the $ with a backslash. the placeholder variables has to set in command bash context (here after su). so you need to do sth like

su -c 'ph="ph"; cat << EOF > script  varinscript=$ph var=\${var} EOF' 
like image 32
Marc Bredt Avatar answered Sep 29 '22 02:09

Marc Bredt