読者です 読者をやめる 読者になる 読者になる

ブログの名前なんて適当で良いのでは

説明を求めるな、記事を読め

sed入門してみた

1.sedとは

sed(stream editor)の略で,ファイルやパイプで渡された入力ストリームに対してテキストの編集をするためのプログラムであり,Unix,Linux系には標準でインストールされている(らしい).

OS X標準のsedは,GNU sedではなくPOSIX sedであり面倒な時がある(後述)ので,個人的にはGNU sedをお勧めする. homebrewを使っている人は以下のコマンドでインストールされ,標準sedGNU sedに変わる.

$ brew install gnu-sed --with-default-names

2.とりあえず使ってみる

行の削除

今,sample.txtという以下の内容のテキストファイルを用意しておく.

    1 => abc
    2 => def
    3 => ghi

1行目を削除したい時

    $sed -e '1d' sample.txt
    2 => def
    3 => ghi 

-eオプションは,スクリプトを指定するものでなくても良いが,!などを含むと面倒なので-eオプションを使ったほうがいい気がする.

もし対象ファイル自体に処理を反映させたい場合は-iオプションをつける.バックアップファイルも生成され元の状態も残るので安心.

スクリプトファイルとして読み込むことも可能で,以下のように.sedでファイルを作る.

 1d

これを読み込むためには,sed -f 1d.sed sample.txtのように-fオプションをつければ良い.

3.sedの仕組みを見てみる

sedスクリプトは[address][command]といった構造になっている.

sedの処理の流れ

  1. ファイルから1行を読み込んでパターンスペース(=バッファ)に格納
  2. addressにマッチする箇所に対してcommand実行
  3. パターンスペースを表示

したがって先ほどの'1d'というスクリプトは,addressが1(=1行目)に対してd(=削除)という処理を行っているということになる.

addressのリテラル

前述したようにaddressにマッチする箇所に対してcommand操作を行うので,addressの表記の仕方は複数あるのでよく使われるだろうものを見ていく.(commandは削除dで統一)

 # 1行目.対象業は数字をそのまま
    $ sed -e '1d' sample.txt
    
    # 1行目と10行目.複数行指定は";"で区切る
    $ sed -e '1d;10d;' sample.txt  


    # 1行目から3行目.範囲指定は","で区切る
    $ sed -e '1,3d' sample.txt 
    
    # 1行目から3行目ずつ削除する.周期は"~"で区切る
    $ sed -e '1~3d' sample.txt 
    
    # 最終行指定は"$"を用いる
    $ sed -e '$d' sample.txt 
    
    # address指定無 => 全行対象
    $ sed -e 'd' sample.txt

様々なcommandたち

p(print)

pコマンドは,addressで指定した行を出力する.

 $ sed -e '1p' sample.txt
    1 => abc
    1 => abc

    2 => def
    3 => ghi

しかし, 他の行まで出力されてしまっている.これはパターンスペースに各行が格納され,その後にpの処理をしているためパターンスペースには[全体の行 + 対象行]が格納されておりそれを出力しているためだと思われる.これを拒否するためには-nオプションをつけて以下のように実行すれば良い.

 $ sed -n -e '1p' sample.txt
    1 => abc
i(insert)

iコマンドは,address指定した行の前の行に対象文字列を挿入する.対象文字列は"i¥"に続けて書く

 $ sed -e '1i¥inserted' sample.txt
   inserted
    1 => abc

    2 => def
    3 => ghi

※実はこの処理がOS Xに標準で入っている方のsedではできなかった.

a(append)

aコマンドは,insertと似ておりaddressで指定した行の後に対象文字列を追記する.対象文字列は"a¥"に続けて書く

 $ sed -e '3a¥appended' sample.txt
    1 => abc
    2 => def
    3 => ghi
    appended
1文字ずつ置換

1文字ずつの置換にはyコマンドが利用できる.以下の例ではaをAに変えてみる. "y/置換元/置換先/"で表記する

 $ sed -e 'y/a/A/' sample.txt
    1 => Abc
    2 => def
    3 => ghi
文字列ずつによる置換

sコマンドを用いると文字列の置換処理をこおなうことができる.

 $ sed -e 's/abc/ABC/'
    1 => ABC
    2 => def
    3 => ghi

これでは1つしか置換されない.すべてを置換する場合は"s/hoge/huga/g"とする.


4. 感想

今となってはテキスト編集はスクリプト言語の役割になってしまったのかもしれない.しかし入門してわかったことは,「sedを使って処理したほうが手軽」という感じる範囲があるということだ.スクリプト言語で書くほどでもないというときには,さっとsedが使えると良いなと感じた.逆にsedだけでやろうとすると面倒なことも出てくる.sedを勉強するメリットは,「これくらいならスクリプト言語書いた方がいいな」と感覚で判断できるようになることだと思う.