sedは指定した箇所を加工するコマンドで,専ら置換に用いられます.
ある文言を何もない状態に置換することで削除を実行したり,位置として行頭を指定して何もないところからスペースへと置換することでインデントを挿入するなど,応用範囲の広いコマンドです.
このページでは,sedコマンドの使用方法について説明しています.

OSによりsedコマンドに若干の違いがあるため,macOSでは一部オプションが使用できなかったり,挙動が異なる場合があります.
HomebrewからインストールできるGNUプロジェクトのgsedコマンドもお試しください.

目次

  1. sによる置換
    1. 正規表現の使用例
    2. 範囲の指定
    3. 検索で引っ掛かったファイルに一斉置換
    4. ヒットしたテキストの再利用
  2. s以外の処理
    1. 出力
    2. 削除
    3. 挿入
    4. ファイルからテキスト挿入
    5. 行ごと置換
    6. trコマンド流の置換
  3. ホールドスペースの利用
  4. スクリプトの分離

sによる置換

基本的な置換は次の形式により行うことができます.

sed 's/置換前/置換後/g' ファイル

sは「置換処理」,gは「該当箇所全てに」の意味を持ちます.
s以外の処理は後述します.
gを書かなかった場合は,各々の行内で一番最初に出てきた箇所のみが置換されます.

必要であれば,置換を実行するための引数であることを-eで明示します.

sed -e 's/置換前/置換後/g' ファイル

オプション-eは複数回用いることができるため,一文で複数の処理を行うことができます.

sed -e 's/置換前1/置換後1/g' -e 's/置換前2/置換後2/g' ファイル

上書き(=入出力するファイルが同一の場合)はオプション-iを用いて次の形にします.

sed -i -e 's/置換前/置換後/g' ファイル

-iオプションはバックアップをとりたいときに-i .bakとするなど,元のファイル名に拡張子をつけて保存します.
空白が指定されると,元のファイル名と同一になるため,上書きになるという理屈です.
macOSでは引数を必ず設定せねばならないため,上書きするには-i ''としてください.

もし置換したい文字列にスラッシュ/を含んでいたら,次のように別の記号を当てることができるというのも知っておくと便利です.

sed 's#置換前#置換後#g' ファイル

正規表現の使用例

置換元として正規表現を用いることができます.
2つ以上の並んだスペースを1つのスペースにするには,正規表現の*(直前の文字の繰り返し)を用いて,

sed 's/  */ /g' ファイル

とします.

行頭を意味する^を指定することで,各行の先頭に文言を追加することができます.

sed 's/^/追加する文字/g' ファイル

行末なら^に代えて$とします.

行頭・行末のスペースを削除するには,

sed 's/^ *//g' ファイル
sed 's/ *$//g' ファイル

とします.

範囲の指定

2行目を置換対象とするなら,アドレスである2を先頭に書き加えて

sed '2s/置換前/置換後/g'

とします.

2行目から5行目までを置換範囲とするなら,2,5として

sed '2,5s/置換前/置換後/g'

とします.
対象範囲を省略した場合は1,$(1行目から最終行まで)が選択されます.

2行目から5行目以外を置換するには!で否定し,

sed '2,5!s/置換前/置換後/g'

とします.

奇数行を指定するには,1~2(1行目より2行ペース)とします.

sed '1~2s/置換前/置換後/g'

文字列を検索して開始行や終了行を指定することもできます.
次はBEGINという文字列が含まれる最初の行から,それ以降でENDという文字列が含まれる最初の行までを置換する例です.

sed '/BEGIN/,/END/s/置換前/置換後/g'

検索で引っ掛かったファイルに一斉置換

ファイル中の文字列を検索するgrepコマンドを併用することで,複数のファイルに一括置換を掛けることができます.
ここではカレントディレクトリから再帰的に検索するため-rオプションを付けています.

grep -rl 単語 ./* | xargs sed -e 's/置換前/置換後/g'

ヒットしたテキストの再利用

置換前に\(\)で括った部分は,置換後に\1等の形で再利用できます.
例えば,

sed 's/\(a\)*\(b\)/\1\2/' ファイル

であればabで括った部分がabに置換されるので,ファイルにxa123bzと書かれていた場合,

xabz

へ置換されます.

正規表現を括ることもでき,ファイルにfile-01と書かれていた場合,

sed 's/file-\([0-9]*\)/\1-file/' ファイル

とすると,01-fileが返ります.

s以外の処理

出力

sに代えてpとすることにより,出力します.
範囲指定すれば,該当行のみ出力されます.

削除

sに代えてdとすることにより,削除処理を実行できます.
特に,/^$/により範囲指定して,

sed '/^$/d' ファイル

とすれば,改行だけの行を削除することができます.
スペースだけの行も含めて削除するなら

sed '/^ *$/d' ファイル

です.

挿入

sに代えてiとすることにより,指定した行番号の「前行」に文字列を挿入することができます.
先頭行の前行に挿入するなら,

sed '1i 文字列' ファイル

とします.

同様に,最終行の「次行」に挿入するなら,aにより

sed '$a 文字列' ファイル

とします.

ファイルからテキスト挿入

iに代えてrを指定することで,ファイルからテキストを挿入することも可能です.
複数行を挿入する場合に有効でしょう.
次は,ヒアドキュメントを用いた例で,HearDoc.txtから読み込んだテキストを2行目に挿入しようとしています.

cat << 'EOS' > HearDoc.txt
本文
EOS
sed '2r HearDoc.txt' ファイル

行ごと置換

行ごと置換するには,sに代えてcを用います.
STRINGを含んだ任意の行で文を置換するには

sed '/STRING/c 置換後の文' ファイル

とします.

trコマンド流の置換

sに代えてyを指定した場合,trコマンドのような置換になります.

例えば,

sed 'y/ABC/123/' ファイル

であればA1B2C3に置換するので,ファイルにaAbBcCと書かれていたとすれば

a1b2c3

と出力されます.

応用例として,yを使用してy/亞惡壓/亜悪圧/のようにすることで,旧字体から新字体へ漢字を置換できます.

ホールドスペースの利用

sedコマンドは1行ずつファイルを読み込んで処理しますが,テキストをストックしつつ処理することもできます.
以下は,通常のパターンスペースからテキストを保持しておくホールドスペースに写しつつ複雑な置換を行う場合のためのメモです.

  • h:パターンスペースからホールドスペースにコピー
  • g:ホールドスペースからパターンスペースにコピー
  • HGhgをそれぞれコピーでなくアペンドにしたもの
  • x:ホールドスペースとローカルスペースを交換

スクリプトの分離

-eの引数となる部分を記したscript.sedというファイルがあるとき,

sed -f script.sed ファイル

によりsedコマンドをスクリプトの通りに実行できます.
ファイルより1行読み込んでスクリプトの全ての行を実行し,次の行を読み込むという順で処理が行われます.