1. ホーム
  2. bash

[解決済み] 変数を展開するheredocを回避する方法は?重複

2022-11-20 15:03:25

質問

ENVからの置換文字列を使ってスクリプトファイルを作成しようとしているが、エスケープを防ぐために

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
"

という良くない結果になります。 myvariable_final はエスケープされず、init スクリプトの依存関係 ($remote_fs, $syslog, $network, $time) にあるものに置き換えられるからです。

#!/bin/bash

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

myvariable_1=toto$PLACEHOLDER1
myvariable_2=titi$PLACEHOLDER2
myvariable_final=\"dynamicvar=\$\{myvariable_1},\$\{myvariable_2}\"
EOF
"

の結果が得られます。

#!/bin/bash

myvariable_1=totomyPlaceholder1Value
myvariable_2=titimyPlaceholder2Value
myvariable_final="dynamicvar=$\{myvariable_1},$\{myvariable_2}"


ウォンテッド/出席結果は、...だったはずです。

#!/bin/bash

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

myvariable_1=toto$PLACEHOLDER1
myvariable_2=titi$PLACEHOLDER2
myvariable_final=\"dynamicvar=\${myvariable_1},\${myvariable_2}\"
EOF
"

どのように解決するのですか?

ただ 'EOF' を使って、変数が展開されないようにします。

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

から man bash :

ここにある書類

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

here-documentsの書式は。

      <<[-]word
              here-document
      delimiter

パラメータ展開、コマンド置換、算術展開、パス名展開を行わない。 またはパス名展開が行われません。 wordの中に引用符で囲まれた文字がある場合 が引用されている場合、区切り文字はwordの引用除去の結果であり、Here-documentの行は展開されません。 の行は展開されません。 もし word が が引用符で囲まれていない場合、Here-Document のすべての行はパラメータ展開、コマンド置換、算術展開の対象となります。 展開、コマンド置換、算術展開が行われます。 . 後者の場合 後者の場合、文字列 \<newline> は無視され \ は引用符で囲む必要があります。 \ , $ そして ` .