UNIX/Linuxの部屋 コマンド:sed


※空白区切りで AND 検索 (例:「ファイル 削除」)

コマンド sed 文字列の置換・削除などの編集を行う

最終更新


UNIX/Linux の sed コマンドは、ストリームエディタと呼ばれるもので、ファイルや標準入力から受け取った文字列に対して、置換・削除等の編集を行うことができる。1979年にリリースされた Version 7 UNIX にて登場した古いコマンドであるため、FreeBSD・Linux・Solaris 等、様々な UNIX 系 OS で使用可能である。

目次:
sed コマンドの基本的な使い方
文字列 aaa を 文字列 bbb に置換するには 's///g' を使う。
% sed 's/abc/def/g' < file > file2
⇒ file 中の文字列 abc を def に変換して file2 に出力する
標準入力に対して使うこともできる。
% command | sed 's/abc/def/g'
⇒ command の出力結果から文字列 abc を def に変換して出力する

aaa の部分には正規表現を使うことができる。
% ls | sed 's/[a-z]/X/g'
⇒ ls の出力の中の小文字のアルファベットを X に変換する。
正規表現部分がシェルに解釈されないように、常に s/// を シングルクォート('') で囲むようにしよう。マッチした部分を再利用したい場合、"\(" 〜 "\)" で囲んだ部分を "\1" で参照することができる。
% ls | sed 's/\(file*\)/cp \1 \1.bak/'
cp file1.txt file1.txt.bak
cp file2.c file2.c.bak
ファイルを上書き更新したい場合は、-i オプションを使う。このとき、バックアップファイルの拡張子を指定する。
% sed -i.bak -e 's/abc/def/' *.txt
→ バックアップファイルとして *.txt.bak が作成される
バックアップ不要である場合は、実装によりやり方が異なる。
% sed -i -e 's/abc/def/' *.txt
→ GNU sed の場合
% sed -i '' -e 's/abc/def/' *.txt
→ BSD・macOS sed の場合

sed の実体
sed はなかなかに複雑かつ高度なコマンドで、実はチューリング完全な言語である。sed の実体は、どの行を対象とするかを表す「アドレス」と、どう編集するかを表す「コマンド」をペアで指定する、というものである。このペアを「スクリプト」と言う。

下記の例をご覧いただくと、アドレスとコマンドの関係性がわかるだろう。

「アドレス: 3行目」を対象に、「コマンド: 行を削除する」場合:
% sed '3d' < file.txt
→ 3行目が削除され、それ以外の行はそのまま出力。アドレスは 3 であり、コマンドは d である。
「アドレス: 3行目」を対象に、「コマンド: 文字列を置換する」場合:
% sed '3s/abc/def/g' < file.txt
→ 3行目のみ abc を def に置換。それ以外の行はそのまま出力。アドレスは 3 であり、コマンドは s/abc/def/g である。
「アドレス: 正規表現 ^d にマッチする行」を対象に、「コマンド: 文字列を置換する」場合:
% ls -l | sed '/^d/s/abc/def/g'
→ 行頭が d である行のみ abc を def に置換。それ以外の行はそのまま出力。アドレスは /^d/ であり、コマンドは s/abc/def/g である。

「アドレス」は省略可能である。その場合、全ての行を対象に「コマンド」が実行される。よく使用する "sed s/aaa/bbb/g" という形は、「アドレス」を省略しているわけである。一方、「コマンド」を省略することはできない。アドレスだけを記載すると、下記のようにエラーとなる。
% sed '10'
sed: -e expression #1, char 2: missing command
→ Linux で確認
sed '10'
sed: 1: "10": command expected
→ FreeBSD で確認

スクリプト (アドレスとコマンドのペア) を複数記述したい場合は、下記のように -e オプションを複数指定する。
% sed -e 's/aaa/AAA/g' -e 's/bbb/BBB/g' file.txt
下記のように sed コマンドを複数パイプでつなげてもよいが、CPU やメモリが若干無駄になることと、-e オプションを複数つらねたのとでは処理結果が異なることを理解した上で使ってほしい。
% sed 's/aaa/AAA/g' < file.txt | sed 's/bbb/BBB/g'

スクリプト (アドレスとコマンドのペア) がない場合、つまり
% command | sed
は何も処理を行わず、command の出力をそのまま表示する。これはつまり sed コマンドのデフォルト挙動は処理結果を出力する、ということを意味する。

sed のアドレス
数字
該当する行を対象とする。
% command | sed '2d'
→ 2行目を削除
数字N,数字M
N行目からM行目を対象とする。
% command | sed '3,5d'
→ 3〜5行目を削除
数字N~数字M
N行目からM行おきの行を対象とする (GNU sed のみ)。
% command | sed '1~2d'
→ 1行目から2行おきの行を削除する (つまり偶数行が表示される)
/正規表現/
正規表現にマッチする行を対象とする。
% command | sed '/[0-9][0-9]/s/abc/def/g'
→ 数字2桁を含む行について、abc を def に置換
\[文字]正規表現[文字]
正規表現にスラッシュを含む場合 /\/usr\/local\/ などとエスケープすればよいが、見づらくなってしまうのを避けたい場合は、\@/usr/local@ などと別の文字を使うことができる。
\X〜X、\_〜_、\!〜! など、どんな文字で挟んでもよい。
% command | sed '\@/usr/local@s/abc/def/g'
→ 数字2桁を含む行について、abc を def に置換

なお、アドレスの最後に "!" を付けると、否定の意味になる。
% command | sed '3!d'
→ 3行目「以外」を削除 (つまり 3行目のみ表示)
% command | sed '3-5!d'
→ 3〜5行目「以外」を削除 (つまり 3〜5行目のみ表示)
% command | sed '/[0-9][0-9]/!s/abc/def/g'
→ 数字2桁を「含まない」行について、abc を def に置換

sed のコマンド
s コマンド
正規表現で置換処理を行う。書式は "s/[置換前文字列]/[置換後文字列]/[フラグ]" である。

\(〜\) で囲んだ部分は、置換文字列内で \数字 として後方参照することができる。
% cat file | sed 's/\([ad]\).\([cf]\)/\1X\2/g'
aXcdXfaXc
012aXc345bcaXc

この例では、[ad] にマッチした部分を \1 で、[cf] にマッチした部分を \2 で参照している。つまり \(〜\) で囲んだ部分は \1、\2、\3、\4、\5 … で参照することができる。

主なフラグを下記に示す。
g: マッチした箇所が複数あった場合、全てを置換する。
g フラグなしの場合、s コマンドは各行に対して、最初に見付かった文字列しか変換を行わない。
% echo aabbccaabb | sed 's/aa/AA/'
AAbbccaabb
→ 最初の aa は AA に置換されるが、2番目以降の aa はそのまま
% echo aabbccaabb | sed 's/aa/AA/g'
AAbbccAAbb
→ 全ての aa が AA に置換される
d コマンド
該当行を削除する。
p コマンド
表示する。

その他
ちなみに perl の文字列置換機能である s/// は、sed が由来であることは言うまでもない。なお、sed より perl の正規表現に慣れている場合は、sed の代わりに
% perl -pe 's/a/b/g' < file
を使う手もある。

ある文字を改行コードに変換、あるいは改行コードをある文字に変換する場合は、sed ではなく tr か perl を使う方がよい。
>> Linuxオンラインマニュアル(man) Linux sed(1)
>> Solaris10オンラインマニュアル(man) Solaris10 sed(1)
>> FreeBSDオンラインマニュアル(man) FreeBSD sed(1)

読み方 sed (UNIXコマンド) [せど] [えす・いー・でぃー] [すえど] [えす・えど] [せっど]

"Stream EDitor" の略。


頑張って書いたおすすめコンテンツ!
クラウドサービス徹底比較・徹底解説