sedによる置換とその応用
sed
は指定した箇所を加工するコマンドで,専ら置換に用いられます.
ある文言を何もない状態に置換することで削除を実行したり,位置として行頭を指定して何もないところからスペースへと置換することでインデントを挿入するなど,応用範囲の広いコマンドです.
このページでは,sed
コマンドの使用方法について説明しています.
OSによりsed
コマンドに若干の違いがあるため,macOSでは一部オプションが使用できなかったり,挙動が異なる場合があります.
HomebrewからインストールできるGNUプロジェクトのgsed
コマンドもお試しください.
目次
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' ファイル |
とします.
範囲の指定
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/' ファイル |
であればa
とb
で括った部分が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 |
行ごと置換
行ごと置換するには,s
に代えてc
を用います.
STRING
を含んだ任意の行で文を置換するには
sed '/STRING/c 置換後の文' ファイル |
とします.
trコマンド流の置換
s
に代えてy
を指定した場合,tr
コマンドのような置換になります.
例えば,
sed 'y/ABC/123/' ファイル |
であればA
を1
,B
を2
,C
を3
に置換するので,ファイルにaAbBcC
と書かれていたとすれば
a1b2c3 |
と出力されます.
応用例として,y
を使用してy/亞惡壓/亜悪圧/
のようにすることで,旧字体から新字体へ漢字を置換できます.
ホールドスペースの利用
sed
コマンドは1行ずつファイルを読み込んで処理しますが,テキストをストックしつつ処理することもできます.
以下は,通常のパターンスペースからテキストを保持しておくホールドスペースに写しつつ複雑な置換を行う場合のためのメモです.
h
:パターンスペースからホールドスペースにコピーg
:ホールドスペースからパターンスペースにコピーH
,G
:h
・g
をそれぞれコピーでなくアペンドにしたものx
:ホールドスペースとローカルスペースを交換
スクリプトの分離
-e
の引数となる部分を記したscript.sed
というファイルがあるとき,
sed -f script.sed ファイル |
によりsedコマンドをスクリプトの通りに実行できます.
ファイルより1行読み込んでスクリプトの全ての行を実行し,次の行を読み込むという順で処理が行われます.