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

sed で置換・行加工する

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

grep が「行を探して表示する」道具だとすれば、sed は「行を加工して流し出す」道具です。名前は stream editor(流れ作業の編集役)に由来し、テキストを1行ずつ受け取って指示どおりに書き換え、結果を出力します。エディタを開いて手で直すのと違い、決まった変換を何百行・何ファイルにも自動で適用できるのが強みで、設定値の一括書き換えやログの整形で絶え間なく登場します。しかも入力を1行ずつ処理するため、巨大なファイルでもメモリを圧迫せずに扱えるのも利点です。sed も正規表現を使い、置換対象の指定には既定で基本正規表現(BRE)の方言が使えます。まずは最頻出の置換から押さえていきましょう。

最頻出の置換 s/old/new/

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] のように囲めます。

g フラグで行内すべてを置換

置換のいちばんのつまずきポイントが、既定では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 なら「先頭から最初の空行まで」を消せます。アドレスとコマンドを組み合わせることで、特定の行だけを狙って書き換えたり消したりでき、ファイル全体に一律で効かせるのとは違うきめ細かい加工ができます。

-n と p で行を抜き出す

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 は取り返しがつかない

ここまでの例は結果を画面に出すだけで、元のファイルは変わりません。ファイルそのものを書き換えたいときは -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 の置換とアドレス指定で自動化でき、手作業のミスと時間を大きく減らせます。

この項目に出てくる用語

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

関連コマンド

sed

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