s コマンドで文字列を置換するとき、「シェル変数を使いたいのに効かない」というトラブルは非常によくあります。
例えば次のようなケースです。
pattern="foo"
replacement="bar"
echo "foo test" | sed 's/$pattern/$replacement/'
期待通りなら "bar test" になるはずですが、実際は置換されず "foo test" のまま。
なぜでしょうか?
目次
1. 原因は「シェル展開されていない」こと
シングルクォート ' ' で囲むと、その中の文字は シェルによる変数展開が行われません。
したがって、上記の $pattern や $replacement は 文字列としてそのまま sed に渡されてしまいます。
2. 解決方法:ダブルクォートを使う
変数を展開させたい場合は、ダブルクォート " を使います。
echo "foo test" | sed "s/$pattern/$replacement/"
→ 出力:
bar test
これで期待通り、foo が bar に置換されました。
3. ただし「特殊文字」に注意!
もし変数に / や &、\ など sed の特殊文字 が含まれている場合、そのままでは思わぬ挙動をします。
例: / を含む場合
replacement="a/b"
echo "foo" | sed "s/foo/$replacement/"
エラーになる、もしくは意図通り動かないことがあります。
4. 対策:区切り文字の変更とエスケープ
区切り文字を / 以外にする
s/// の区切り文字は / 以外でもOK。たとえば # を使うと安全です。
replacement="a/b"
echo "foo" | sed "s#foo#$replacement#"
→ 出力:
a/b
& や \ を含む場合
&は「マッチした文字列」を意味するので、リテラルとして使うにはエスケープが必要です。- バックスラッシュ
\は二重解釈されやすいので、\を\\にしておくと安心です。
5. まとめ
- シングルクォート
' 'では変数は展開されない - 変数を使いたいときはダブルクォート
" "を使う /を含むなら区切り文字を変える(#や|など)&や\はエスケープが必要
編集後記
私も昔、設定ファイルの置換をシェルスクリプトで書いていて「変数が展開されない!sedが壊れてるのか?」と数時間悩みました…。
原因は単純で「シングルクォートで囲んでいた」だけ。クォートの違いを理解してからは一気にトラブルが減りました。
あわせて読みたい


【コマンド詳細】sedコマンドの使い方とオプションまとめ
sed コマンドとは? sed (Stream Editor) は、LinuxやUNIXシステムで使われるストリーム形式のテキストエディタです。ファイルを直接開くことなく、以下のようなテキス…
よくあるエラーと解決方法まとめ
あわせて読みたい


【完全版】sedエラー大全|よくある原因と解決方法まとめ
sed は Linux 環境でテキスト処理を行う際に非常に便利なコマンドですが、オプションや正規表現の違い、環境依存の仕様によって多くのエラーが発生します。初心者はもち…
