web-dev-qa-db-ja.com

ヒアドキュメントの変数の展開を避ける方法は?

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)の1つとして置換されないため、結果は良くありません

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

'EOF'を使用して、変数が展開しないようにします。

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

man bashから:

ヒアドキュメント

このタイプのリダイレクトは、区切り文字のみ(末尾の空白なし)を含む行が表示されるまで、現在のソースから入力を読み取るようシェルに指示します。その時点までに読み取られたすべての行は、コマンドの標準入力として使用されます。

ヒアドキュメントの形式は次のとおりです。

      <<[-]Word
              here-document
      delimiter

パラメーターの展開、コマンドの置換、算術展開、またはパス名の展開は、Wordでは実行されません。 Wordの文字が引用符で囲まれている場合、区切り文字はWordで引用符を削除した結果であり、ヒアドキュメントの行は展開されません。 Wordが引用符で囲まれていない場合、ヒアドキュメントのすべての行は、パラメーター展開、コマンド置換、および算術展開の対象となります。後者の場合、文字シーケンス\は無視され、文字\、$、および `を引用するには\を使用する必要があります。

137
fedorqui

suコマンドを使用する場合、コマンド自体を単一引用符で囲み、バックスラッシュで$をエスケープします。プレースホルダー変数は、コマンドbashコンテキスト(ここではsuの後に)で設定する必要があります。だからあなたは

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