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 環境でテキスト処理を行う際に非常に便利なコマンドですが、オプションや正規表現の違い、環境依存の仕様によって多くのエラーが発生します。初心者はもち…