如何避免heredoc扩展变量?

时间:2015-01-13 11:12:54

标签: bash escaping substitution heredoc

我尝试使用ENV中的替换字符串创建脚本文件,但也想阻止某些字符串转义

export PLACEHOLDER1="myPlaceholder1Value"
export PLACEHOLDER2="myPlaceholder2Value"
sudo /bin/su -c "cat << EOF > /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
"

由于 myvariable_final 未被转义并被替换为init脚本依赖项($ 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=,"

如果我尝试将反斜杠\置于美元$后面,我设法避免替换,但我收到了不必要的反斜杠\

export PLACEHOLDER1="myPlaceholder1Value"
export PLACEHOLDER2="myPlaceholder2Value"
sudo /bin/su -c "cat << EOF > /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
"

结果:

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

希望/出席的结果应该是:

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

通过在 EOF 周围加上引号来解决,并在需要时使用反斜杠来控制转义

export PLACEHOLDER1="myPlaceholder1Value"
export PLACEHOLDER2="myPlaceholder2Value"
sudo /bin/su -c "cat << 'EOF' > /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
"

2 个答案:

答案 0 :(得分:124)

只需使用'EOF'来阻止变量扩展:

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

来自man bash

  

此处文件

     

这种重定向指示shell从中读取输入   当前源直到一行只包含分隔符(没有   可见尾随空白)。所有读到的那一行都是   然后用作命令的标准输入。

     

here-documents的格式为:

      <<[-]word
              here-document
      delimiter
     

没有参数扩展,命令替换,算术扩展,   或者对word执行路径名扩展。如果单词中有任何字符   引用,分隔符是单词引用删除的结果,和   here-document中的行未展开。 如果是的话   如果没有引用,here-document的所有行都会受到参数的影响   扩展,命令替换和算术扩展。在里面   后一种情况,字符序列\被忽略,并且   必须用来引用字符\,$和`。

答案 1 :(得分:1)

当使用su命令时,将命令本身放在sigle引号中,然后用反斜杠转义$。占位符变量必须在命令bash上下文中设置(此处为su)。所以你需要做某事......

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