🐧 Linux 総合学習プラットフォーム
正規表現・テキスト処理 ・ 中級

sed で置換・行加工する

sed は1行ずつ読み込んでテキストを加工するストリームエディタです。最もよく使うのが置換で、sed 's/古い/新しい/' の形で各行の最初の一致を書き換えます。行内すべてを置換するには末尾に g を付けて s/old/new/g とします。既定では結果を画面に出すだけでファイルは変わらず、-i を付けて初めてファイルを直接書き換えます。置換のほか 3d で3行目を削除、-n と p で特定行だけ表示するなど、行単位の加工を自動化できます。

grep が「行を探して表示する」道具だとすれば、sed は「行を加工して流し出す」道具だ。

名前は stream editor(流れ作業の編集役)に由来し、テキストを1行ずつ受け取って指示どおりに書き換え、結果を出力する。

🔗
たとえsed は流れ作業のベルトコンベヤだ。1行ずつ流れてくる品物に決まった加工を施し、そのまま次へ送り出す。手で1つずつ直すのとは速さが違う。

エディタを開いて手で直すのと違い、決まった変換を何百行・何ファイルにも自動で適用できるのが強みで、設定値の一括書き換えやログの整形で絶え間なく登場する。

しかも入力を1行ずつ処理するため、巨大なファイルでもメモリを圧迫せずに扱えるのも利点だ。

sed も正規表現を使い、置換対象の指定には既定で基本正規表現(BRE)の方言が使える。まずは最頻出の置換から押さえていこう。

🔁 いちばん使うのは、たった一つの書式

sed でもっともよく使うのが置換だ。書式は s/old/new/ で、s は substitute(置換)の頭文字、/ は区切り記号だ。

s/old/new/置換探す側(正規表現可)置き換える側

echo 'apple apple apple' | sed 's/apple/orange/' を実行すると orange apple apple となり、各行の最初の一致だけが書き換わる。

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| は、同じことを / 区切りで書くより格段に読みやすくなる。

コツ置換対象にスラッシュを含むときは、区切りを 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 がすべて変わる。

つまずき既定では1行につき最初の1個しか置換しない。行内すべてを変えるには末尾に g を付ける。初学者がほぼ必ず一度はここで引っかかる。

「g を付けないと1個だけ」。これは初学者がほぼ必ず一度は引っかかる落とし穴なので、最初に強く意識しておくとよい。

逆に、各行で1個だけ直したいときは g を付けない、という使い分けになる。

🎯 ファイル全体ではなく、狙った行だけ直したいときは

コマンドの前に「アドレス」を置くと、どの行に処理を効かせるかを指定できる。

行番号で 2s/b/BBB/ と書けば2行目だけ置換、範囲で 2,3d と書けば2行目から3行目を削除する(d は delete の頭文字)。

アドレスには行番号だけでなく /正規表現/ も使え、sed '/^#/d' file は「# で始まる行を削除」、つまりコメント行を消す指定になる。これは grep -v '^#' と同じ結果を sed 側で実現する書き方だ。

sed '/^#/d' file は # で始まる行を削除(コメント消し)。sed '/^server/s/old/new/' なら server で始まる行に限って置換する。

さらに置換と組み合わせて 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 を使うと、対象行が「自動出力+p」で二重に出る。sed '2p' file は2行目が2回出てくる。抜き出しは -n と p をセットで。

「行を抜き出す」用途では -n と p をセットで使うのが基本だと覚えてほしい。

⚠ 取り返しのつかない一手に、どう備えるか

ここまでの例は結果を画面に出すだけで、元のファイルは変わらない。ファイルそのものを書き換えたいときは -i(in-place)を付ける。sed -i 's/2025/2026/g' memo.txt とすると、memo.txt が直接書き換わる。

ただし -i は元に戻せないため、扱いには最大の注意が要る。

💡
ポイント-i はファイルを直接書き換え、元に戻せない。まず -i 無しで結果を確かめ、本番では sed -i.bak '…' file で file.bak を残すのが安全だ。

安全策は二段構えだ。まず -i を付けずに実行して結果を画面で確かめ、問題なければ -i を付ける流れにすること。さらに本番ファイルでは、cp memo.txt memo.txt.bak のように事前にバックアップを取るか、sed -i.bak 's/.../.../' file と書いて file.bak を自動で残すのが確実だ。

複数のファイルに同じ加工をまとめてかけたいときは sed -i 's/old/new/g' *.conf のようにワイルドカードで対象を広げられるが、そのぶん影響範囲も広がるので、事前の確認とバックアップはいっそう大切になる。

実務では、設定値の一括更新、不要行の削除、特定行の抽出、ログの整形といった定型作業を sed の置換とアドレス指定で自動化でき、手作業のミスと時間を大きく減らせる。

この項目に出てくる用語

sedせど
1行ずつ加工するストリームエディタ。置換 s/// が代表的。
置換(s コマンド)ちかん
sed の s/old/new/ で文字列を書き換える操作。

関連コマンド

sed

▶ 学習アプリでこの続きを学ぶ・演習する