Corredor

ウェブ、プログラミングの勉強メモ。

場当たり的に覚えた sed の使い方

テキストファイルの置換に使う sed (セド) コマンド。独特の構文で体系的に覚えられていないのだが、やりたいことから逆引きして場当たり的に覚えてきたことをまとめてみようと思う。

sed コマンドは OS によって若干の差異があるが、基本的には同様に使える。今回の記事は、Windows の GitBash、MacOS 標準のターミナル、Linux 環境のどこかで試したメモをベースに書いているので、環境差異で動かなかった場合はご容赦を…。

ちなみに、sed の名称は「stream editor」の略らしい。

基本的な使い方

sed コマンドの基本的な構文は以下のとおり。

$ sed 【オプション】 【スクリプト】 【操作対象のファイル名】

【スクリプト】 は文字列操作のための式のこと。本来 -e オプションで渡すモノだが、-e オプションは省略できるので上のように書いた。

テキストを置換する

任意のテキストを置換するには、以下のように書く。コレが最も基本的なパターン。

$ sed 's/【置換したい文字列】/【置換後の文字列】/g' 【ファイル名】

置換したい文字列 (検索する文字列) はケースセンシティブ、大文字小文字を区別するので、hogeHOGE は別物になることに注意。

g オプション

スクリプト内の g は Global の意味。sed は入力を行単位に処理するのだが、g オプションを付けない場合はその1行で最初に出てきた文字列しか置換しない。

つまり、例えば

hoge foo hoge who
hoge bar hoge baz

というテキストファイルがあったとして、g オプションなしで hoge を置換すると

$ sed 's/hoge/fuga/' example.txt
fuga foo hoge who
fuga bar hoge baz

このように、その行の2つ目以降の hoge は置換されない。

g オプションを付ければ、以下のように全て置換される。

$ sed 's/hoge/fuga/g' example.txt
fuga foo fuga who
fuga bar fuga baz

正規表現との組み合わせ

この式の中では正規表現も使えるので、^ で行頭、$ で行末を示したり、.* で任意の文字列を指定したりできる。

# 行頭が「example」で始まるものを「replaced」にする。行頭を指定しているので g オプションの有無は関係なし
$ sed 's/^example/replaced/' example.txt

# 行末が「example」で終わるものを「replaced」にする。これも g オプションの有無は関係なし
$ sed 's/example$/replaced/' example.txt

# 「ex【任意の文字列】le」に該当する箇所を「replaced」に置換する
$ sed 's/ex.*le/replaced/g' example.txt

デリミタ

式の中では、基本的には / がデリミタとして扱われるので、文字列中に / を含む場合はエスケープが必要になる。

# 「http://」部分を「ftp://」に置換する
$ sed 's/http:\/\//ftp:\/\//g' example.txt

なお、デリミタは s の次に書いた文字がデリミタとして使われるので、@ などに変更しても良い。

# デリミタを「@」に変更。こうすれば「/」をエスケープしてもしなくても書ける
$ sed 's@http://@ftp://@g' TEST.txt

行を削除する

これまでの 's/検索/置換/' とは別に、/検索/d という式を使うと、条件に合う行をまるごと削除できる。

# 「hoge」を含む行を削除する
$ sed '/hoge/d' example.txt

ファイルに上書き保存する

これまでのコマンドだと、置換結果は標準出力に表示されるだけで、ファイルに置換結果が反映されない。操作対象のファイルに置換結果を反映して上書き保存するには、-i オプションを使う。

# 「example.txt」中の「hoge」を「fuga」に置換して上書き保存する
$ sed -i 's/hoge/fuga/g' example.txt

より実践的なサンプル

何らかの理由で、設定ファイルの特定行をコメントアウトしたり、外したりしたい時。

# 何かの設定ファイル
my_setting: HOGEFUGA

my_setting で始まる行の先頭に # を付与してコメントアウトし、上書き保存する。

$ sed -i 's/^my_setting/# my_setting/g' example.conf

こうしてコメントアウトした行をまた戻す時。

# 何かの設定ファイル
# my_setting: HOGEFUGA

今度は # my_setting で始まる行を検索してやれば良い。

$ sed -i 's/^# my_setting/my_setting/g' example.conf

以上

今回紹介したのは sed の機能のごく一部だが、これらの知識だけでも一旦はそれらしく置換処理ができるようになったと思う。

sed や正規表現をきちんと読める人もなかなか多くはないと思うので、あまり極端に多用しすぎず、人間が読んで分かりやすい範囲の利用に留めておいた方が良いかな、と個人的には思う。

参考

sed & awkプログラミング 改訂版 (A nutshell handbook)

sed & awkプログラミング 改訂版 (A nutshell handbook)

sed & awk デスクトップリファレンス

sed & awk デスクトップリファレンス