Top Pageに戻る。


sed の使い方

テキストをちょっと加工するには「sed」が便利。 sedの使い方を簡単にまとめておきました。 Windowsで使いたいならば、 dos用のsedがvectorに ありました。


目次


1.基本的な使い方

たとえば nantoka.sed というスクリプトファイルで inputfile.txt というファイルをいじりたいなら、 次のようなコマンドを実行する。

sed -f nantoka.sed inputfile.txt

ちょっと使うだけならスクリプトファイルを使わずにコマンドラインに書く。

sed  '命令' inputfile.txt
ただし、コマンドラインに書くときは '命令' の後に p(表示せよ) と d(新たに次の行を読み込め) が省略されていると解釈されます(下の例参照)

2.スクリプトファイルの書き方

2.1 スクリプトファイルの基本形式

# コメント
「実行条件1」「命令1」
「実行条件2」{
        「命令2.1」
        「命令2.2」
}
……
d

2.2 「命令」とは

p
読みこんだ文字列+改行コードを書き出す

P
読みこんだ文字列の中ではじめに出てくる改行コードまでを書き出す。 読みこんだ文字列に改行コードがないときは、 読みこんだ文字列+改行コードを書き出す。

N
inputfile.txtから次の行を読みこみ、記憶していた文字列に追加

q
読みこんだ文字列+改行コードを書き出してから終了

d
inputfile.txtから次の行を読み込み直してスクリプトの先頭に戻る

D
読みこんだ文字列の中ではじめて改行コードが出てくるまでの部分を記憶から消し、 スクリプトの先頭に戻る。読みこんだ文字列に改行コードがないときは、 inputfile.txtから次の行を読み込み直してスクリプトの先頭に戻る

s/正規表現/文字列/
読みこんだ文字列の中で「正規表現」にマッチする部分を「文字列」で置きかえる。 複数の部分がマッチするときは、はじめにマッチした部分にのみ置換を行う。 置き換える文字列に改行を入れたいなら、 「\」の後に改行を入れる。例 4.2参照。

s/正規表現/文字列/g
読みこんだ文字列の中で「正規表現」にマッチする部分を「文字列」で置きかえる。 複数の部分がマッチするときは、すべてのマッチした部分に置換を行う。

s/正規表現/文字列/3
読みこんだ文字列の中で3番目に「正規表現」にマッチする部分のみを「文字列」で置きかえる。

y/文字列A/文字列B/
読みこんだ文字列の中で「文字列A」に含まれる文字を「文字列B」の 同じ位置にある文字で置きかえる。

{命令A 命令B …}
「命令A」、「命令B」、…の順に実行


2.3 「実行条件」とは

4
4行目ならば。

2,4
2,3,4行目ならば。

例.5行目から10行目だけを表示する。
5,10p
d

同じことをスクリプトファイルを使わずに実行する場合は、 -n オプションをつけて 自動的に p が付加されることをやめさせます。

sed -n '5,10p' inputfile.txt
$
最後の行ならば。

例.最後の行だけを表示する。
$p
d

スクリプトファイルを使わずに実行する場合は、上と同様に -n オプションをつける必要があります。

sed -n '$p' inputfile.txt
/正規表現/
正規表現にマッチするならば。

例.#で始まる行以外を表示する。
sed '/^#/d' inputfile.txt
条件1,条件2
条件1が成立する行から条件2が成立する行までならば。

条件!
条件が成立しない行ならば。

何も書かない
無条件に。

2.4 ループ

: 「ループの名前」
命令
b 「ループの名前」

使い方は例aaaからbbbに囲まれた部分を抽出する、削除するを参照。


3. 正規表現

3.1 基本

abc
文字列 abc

[abc]
「a」または「b」または「c」

[a-c]
[abc]と同じ意味。[a-z]ならば、小文字のアルファベット一文字。

[^abc]
「a」ではなく「b」でもなく「c」でもない一文字。

[^0-9a-zA-Z]
アルファベットと数字以外

.
任意の1文字

*
直前の正規表現の 0 回以上の繰り返し

^
正規表現の先頭に置かれると、行頭を表す

$
正規表現の最後尾に置かれると、行のおわりを表す

\\, \/, \., \[, \], \n
おのおの、「\」, 「/」, 「.」, 「[」, 「]」,「改行文字」 をあらわす。 ちなみに、スペースやタブはそのまま打てばいいです。

3.2 正規表現にマッチした部分を置き換え後の文字列に使う

&
マッチした正規表現全体を表す

\(正規表現\)
\(と\)にはさまれた部分を\1,\2,...で参照できる。\1なら1番目に現れた\(正規表現\)、 \2なら2番目に現れた\(正規表現\)など。

例.Mr. Green を Green-san に変える。
s/Mr\. \([A-Za-z]*\)/\1-san/g
p
d

4. 例

4.1 aaaからbbbに囲まれた部分を抽出する、削除する

<div class="article">という文字列から </div>という文字列に囲まれた部分のみを抜き出して表示する。

/<div class="article">/{
	:loop
	N
	/<\/div>/!b loop # </div>を含まない行ならば:loopに戻る(b)
	# ここでは<div class="article">を含む行から</div>を含む行までを記憶(N)している
	s/^.*\(<div class="article">.*<\/div>\).*$/\1/ # 囲まれた部分以外を記憶から削除
	p
}
d # 囲まれた部分以外は表示(p)しない

逆に、上記の部分のみを削除するには次のスクリプトファイルを使えばよい。

/<div class="article">/{
	:loop
	N
	/<\/div>/!b loop
	# ここまでは上と同じ
	s/<div class="article">.*<\/div>// # 囲まれた部分を記憶から削除
}
p
d

4.2 ピリオドごとに改行を追加

A is B. B is C. C is D.
E is F. G is H.

という文章を

A is B.
B is C.
C is D.
E is F.
G is H.

にする。

# ピリオドごとに改行を追加して、だらだらと長い文章を整形する。
s/\. */.\
/g
p
d

4.3 改行をすべて削除

すべての行を読み込んでから改行を消すことで、改行を削除できる。

:loop
N
$!b loop
s/\n//g

同じことをコマンドラインでするには、セミコロン(;)で各行をつなげればよい。

sed ':loop; N; $!b loop; s/\n//g' inputfile.txt

4.4 YYYYMMDDをYYYY-MM-DDに

たとえば2012年3月31日に作った資料を 20120331_memo.txtなどという名前で保存していましたが、 ある日、2012-03-31_memo.txtのほうが圧倒的に見やすく思えてきました。

というわけで、これまで作ったYYYYMMDD○○という形式のファイルやディレクトリの名前を、 YYYY-MM-DD○○に変更するための sedスクリプトを作りました。 西暦を2桁で表していた場合にも対応しています。

/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/{ # YYYYMMDD○○を変換
	s/^\([0-9][0-9][0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9].*$\)/mv \1\2\3 \1-\2-\3/
	p
}
/^[0-9][0-9][0-9][0-9][0-9][0-9][^0-9]/{ # YYMMDD○○を変換
	s/^\([0-9][0-9][0-9][0-9]\)\([0-9][0-9].*$\)/mv \1\2 \1-\2/
	p
}
d
UNIX系OSやWindowsでCygwinをインストールしているならば、 上のスクリプトをYYYYMMDD_to_YYYY-MM-DD.sedとして保存して、 次のようにすれば名前の変更ができます。
\ls | sed -f YYYYMMDD_to_YYYY-MM-DD.sed > tmp.sh
sh tmp.sh

5. リンク


Top Pageに戻る。