解説
複数行を書いたら変数が展開された?Bashのヒアドキュメントで文字を保とう
<<DOCと<<'DOC'を比較し、複数行入力の変数展開・バックスラッシュを確認。終端の位置、出力先の引用符、安全な練習場所を整理。

ターミナルから数行まとめてファイルへ書いたら、$で始まる文字が値へ変わってしまった。Bashのヒアドキュメントでは、終端に使う言葉を引用するかどうかで扱いが変わるよ。
ヒアドキュメントは、決めた終端の行までをコマンドの入力として渡す書き方。このページでは、複数行の文章をそのまま保つ方法を覚える。Bashのターミナルと、一時フォルダーにファイルを作れる環境が必要だよ。
終端の言葉に引用符がない例
(
set -e
task_here_dir=$(mktemp -d) || exit
practice_label='blue card'
cat > "$task_here_dir/expanded.txt" <<DOC
label=$practice_label
literal=\$practice_label
DOC
cat > "$task_here_dir/literal.txt" <<'DOC'
label=$practice_label
literal=\$practice_label
DOC
printf '%s\n' 'expanded:'
cat "$task_here_dir/expanded.txt"
printf '%s\n' 'literal:'
cat "$task_here_dir/literal.txt"
)
新しく作った一時フォルダーの二ファイルだけを書き、元の作業場所やファイルは変えない。catはここで受け取った入力を、>の先のファイルへ書き出しているよ。
最初の<<DOCでは、本文の$practice_labelがblue cardへ展開される。二行目は$の前にバックスラッシュを置いているので、$practice_labelという文字として残る。
終端を引用すると本文を展開しない
二つ目の<<'DOC'では、終端に使う言葉のところを一重引用符で囲んでいる。その場合、本文の変数展開などは行われず、バックスラッシュも今回の行の文字として残るよ。
出力は次の六行になる。
expanded:
label=blue card
literal=$practice_label
literal:
label=$practice_label
literal=\$practice_label
ファイルにシェルの設定例や、$を含む説明文を文字として保存したいなら、この違いを確認したいね。終端の引用符は、書き込んだファイルの内容へ付くものではないんだ。
最後のDOCには引用符を付けない
開始側は<<'DOC'でも、閉じる行はDOCだけにする。末尾にスペースを足したり、別の文字を付けたりすると、期待した終端にならないよ。
今回の例は<<なので、終端行の先頭にも空白を入れていない。インデントしたい場合の<<-は、先頭のタブを扱う別の指定で、スペースを何個でも無視する指定ではない。まずはこの例のように終端を行頭へ置いて試そう。
本文の引用と、出力先の引用は別
出力先を"$task_here_dir/literal.txt"のように二重引用符で囲むのは、パスを一つの引数として扱うため。本文を展開するかどうかは、<<の後ろの終端指定で決める。片方だけ引用すれば、もう片方にも同じ効果が及ぶわけではないよ。
終端が引用されていない本文では、変数のほか、コマンド置換や算術展開も関係する。誰かから受け取った複数行を、実行する断片として貼り付けず、保存したい文字なのかを確認しよう。今回の練習は自分で書いた固定の行だけを使うよ。
元へ戻すときは練習場所だけを扱う
括弧の処理が終われば、練習の変数は親の環境へ残らない。一時フォルダーと二つのファイルは残るので、必要な出力を確かめてから、その練習用の場所だけを片付けられる。

みんなのコメント 0
感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。
最初のコメントをどうぞ。