sed で置換・行加工する
sed は1行ずつ読み込んでテキストを加工するストリームエディタです。最もよく使うのが置換で、sed 's/古い/新しい/' の形で各行の最初の一致を書き換えます。行内すべてを置換するには末尾に g を付けて s/old/new/g とします。既定では結果を画面に出すだけでファイルは変わらず、-i を付けて初めてファイルを直接書き換えます。置換のほか 3d で3行目を削除、-n と p で特定行だけ表示するなど、行単位の加工を自動化できます。
grep が「行を探して表示する」道具だとすれば、sed は「行を加工して流し出す」道具だ。
名前は stream editor(流れ作業の編集役)に由来し、テキストを1行ずつ受け取って指示どおりに書き換え、結果を出力する。
エディタを開いて手で直すのと違い、決まった変換を何百行・何ファイルにも自動で適用できるのが強みで、設定値の一括書き換えやログの整形で絶え間なく登場する。
しかも入力を1行ずつ処理するため、巨大なファイルでもメモリを圧迫せずに扱えるのも利点だ。
sed も正規表現を使い、置換対象の指定には既定で基本正規表現(BRE)の方言が使える。まずは最頻出の置換から押さえていこう。
🔁 いちばん使うのは、たった一つの書式
sed でもっともよく使うのが置換だ。書式は s/old/new/ で、s は substitute(置換)の頭文字、/ は区切り記号だ。
echo 'apple apple apple' | sed 's/apple/orange/' を実行すると orange apple apple となり、各行の最初の一致だけが書き換わる。
old の部分には正規表現が書けるので、s/[0-9]\{4\}/YEAR/ のようにパターンで対象を指定することもできる。
区切りの / は、置換対象にスラッシュを含むとき(パスの書き換えなど)に s|old|new| や s#old#new# のように別の記号へ変えられ、\/ だらけになるのを避けて読みやすくできる。たとえばパスを書き換える s|/usr/local|/opt| は、同じことを / 区切りで書くより格段に読みやすくなる。
new の側では & が「一致した文字列全体」を表すので、s/error/[&]/ とすれば error を [error] のように囲める。
❶ 1個しか変わらない、なぜだ
置換のいちばんのつまずきポイントは、たいてい同じ場所だ。既定では1行につき最初の1個しか置換しないのである。
行内のすべての一致を置き換えるには、末尾に g(global)フラグを付ける。echo 'apple apple apple' | sed 's/apple/orange/g' とすれば orange orange orange となり、行内の apple がすべて変わる。
「g を付けないと1個だけ」。これは初学者がほぼ必ず一度は引っかかる落とし穴なので、最初に強く意識しておくとよい。
逆に、各行で1個だけ直したいときは g を付けない、という使い分けになる。
🎯 ファイル全体ではなく、狙った行だけ直したいときは
コマンドの前に「アドレス」を置くと、どの行に処理を効かせるかを指定できる。
行番号で 2s/b/BBB/ と書けば2行目だけ置換、範囲で 2,3d と書けば2行目から3行目を削除する(d は delete の頭文字)。
アドレスには行番号だけでなく /正規表現/ も使え、sed '/^#/d' file は「# で始まる行を削除」、つまりコメント行を消す指定になる。これは grep -v '^#' と同じ結果を sed 側で実現する書き方だ。
さらに置換と組み合わせて sed '/^server/s/old/new/' のように書けば、「server で始まる行に限って置換する」といった条件付きの加工もできる。
末尾を表す $ をアドレスに使って $d とすれば最終行だけを削除でき、行番号と組み合わせた 1,/^$/d なら「先頭から最初の空行まで」を消せる。
アドレスとコマンドを組み合わせることで、特定の行だけを狙って書き換えたり消したりでき、ファイル全体に一律で効かせるのとは違うきめ細かい加工ができる。
🔍 grepのように行を抜き出すこともできるのか
sed は既定ですべての行を出力するが、-n を付けると自動出力をやめる。そこへ p(print)コマンドを組み合わせると、指定した行だけを表示できる。
sed -n '2,4p' /etc/passwd は2行目から4行目だけを出し、head と tail を合わせたような切り出しになる。sed -n '/^server/p' file のように /パターン/p と組み合わせれば、一致する行だけを抜き出すこともでき、grep の代わりにもなる。
ここで一つ戸惑いがちな点がある。-n を付けずに p を使うと、対象行が「自動出力+p」で二重に表示されてしまうのだ。実際 sed '2p' file を実行すると、2行目だけが2回出てくる、という妙な結果になる。
「行を抜き出す」用途では -n と p をセットで使うのが基本だと覚えてほしい。
⚠ 取り返しのつかない一手に、どう備えるか
ここまでの例は結果を画面に出すだけで、元のファイルは変わらない。ファイルそのものを書き換えたいときは -i(in-place)を付ける。sed -i 's/2025/2026/g' memo.txt とすると、memo.txt が直接書き換わる。
ただし -i は元に戻せないため、扱いには最大の注意が要る。
安全策は二段構えだ。まず -i を付けずに実行して結果を画面で確かめ、問題なければ -i を付ける流れにすること。さらに本番ファイルでは、cp memo.txt memo.txt.bak のように事前にバックアップを取るか、sed -i.bak 's/.../.../' file と書いて file.bak を自動で残すのが確実だ。
複数のファイルに同じ加工をまとめてかけたいときは sed -i 's/old/new/g' *.conf のようにワイルドカードで対象を広げられるが、そのぶん影響範囲も広がるので、事前の確認とバックアップはいっそう大切になる。
実務では、設定値の一括更新、不要行の削除、特定行の抽出、ログの整形といった定型作業を sed の置換とアドレス指定で自動化でき、手作業のミスと時間を大きく減らせる。