web-dev-qa-db-ja.com

bashヒアドキュメント内で変数を使用する

私はbash heredoc内の変数を補間しようとしています:

var=$1
Sudo tee "/path/to/outfile" > /dev/null << "EOF"
Some text that contains my $var
EOF

これは期待どおりに機能しません($varは文字通りに扱われ、展開されません)。

ファイルを作成するにはSudoが必要なため、Sudo teeを使用する必要があります。次のようなことをする:

Sudo cat > /path/to/outfile <<EOT
my text...
EOT

>outfileは、Sudoを使用していない現在のシェルでファイルを開くため、機能しません。

171
Jon

最初の質問への回答では、区切り文字を引用符で囲んでいるため、パラメーターの置換はありません- bashのマニュアルでは

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

      <<[-]Word
              here-document
      delimiter

Wordでは、パラメーター展開、コマンド置換、算術展開、またはパス名展開は実行されません。 Wordの文字が引用符で囲まれている場合、delimiterはWordで引用を削除すると、ヒアドキュメントの行は展開されません。 Wordが引用符で囲まれていない場合、ヒアドキュメントのすべての行がパラメーター展開、コマンド置換、および算術展開の対象になります。 [...]

<<EOFの代わりに<< "EOF"を使用するように最初の例を変更すると、機能することがわかります。

2番目の例では、シェルはパラメーターSudoでのみcatを呼び出し、リダイレクトは元のユーザーとしてSudo catの出力に適用されます。あなたが試してみると動作します:

Sudo sh -c "cat > /path/to/outfile" <<EOT
my text...
EOT
229
Mark Longair

<<EOFで引用符を使用しないでください:

var=$1
Sudo tee "/path/to/outfile" > /dev/null <<EOF
Some text that contains my $var
EOF

変数展開は、here-docs内のデフォルトの動作です。ラベルを引用符で囲むことにより、その動作を無効にします(一重引用符または二重引用符で)。

88
mob

ここでの以前の回答に対する後期コロリーナとして、おそらくあなたはsomeが欲しいがallではない状況に陥るでしょう補間される変数。バックスラッシュを使用してドル記号とバックティックをエスケープすることでそれを解決できます。または、静的テキストを変数に入れることができます。

Name='Rich Ba$tard'
dough='$$$dollars$$$'
cat <<____HERE
$Name, you can win a lot of $dough this week!
Notice that \`backticks' need escaping if you want
literal text, not `pwd`, just like in variables like
\$HOME (current value: $HOME)
____HERE

デモ: https://ideone.com/rMF2XA

引用メカニズム(\____HEREまたは"____HERE"または'____HERE')は、すべての変数補間を無効にし、ヒアドキュメントをリテラルテキストに変換します。

一般的なタスクは、ローカル変数とスクリプトを組み合わせて、異なるシェル、プログラミング言語、またはリモートホストで評価することです。

local=$(uname)
ssh -t remote <<:
    echo "$local is the value from the Host which ran the ssh command"
    # Prevent here doc from expanding locally; remote won't see backslash
    remote=\$(uname)
    # Same here
    echo "\$remote is the value from the Host we ssh:ed to"
:
14
tripleee