sed - テキストを置換や編集をする

sedコマンドは、テキストを置換するだけではなく、aコマンドやiコマンドでテキストの行の前後に文字列を追記することも可能です。
さらに、アドレスを用いれば、より複雑にテキストの編集を行うことができます。

コマンド例の想定

コマンドの例として、以下のような「apple」、「onion」、「yuzu」の重複順列でできたテキストファイルを想定します。

itemtext.txt ▼表示

また、sedコマンドのスクリプトが書かれたファイルをscript.sedとします。

パターンスペースとホールドスペース

sedコマンドは、基本的に入力行をバッファに入れます。
このバッファのことをパターンスペース(pattern space)といいます。

また、sedコマンドは、パターンスペースとは別に補助的なバッファを持ちます。
これをホールドスペース(hold space)といいます。

sedコマンドの基本動作は行ごとに、

1.入力の行をパターンスペースに入れる。
2.sedコマンドのスクリプトを実行する。(パターンスペースの変更や表示等)
3.パターンスペースを表示する。(-nオプションがある場合は行わない)

を繰り返します。

sedコマンドのスクリプトのアドレスは一種の条件分岐のように扱うことができます。
つまり、アドレスを用いることでパターンスペースとホールドスペースをうまく使うことができます。

スクリプトをファイルから読み込む
(-fオプション)

-fオプションは、sedコマンドのスクリプトが書かれたファイルを読み込むことができます。
この例では、script.sedがsedコマンドのスクリプトが書かれたファイルになります。

script.sedでは、sコマンドを用いてそれぞれの行で初めに現れた「apple」を「melon」に変えるスクリプトが書かれています。

また、これ以降の例では、sedコマンドのスクリプトをファイルに記述する場合、script.sedに記述します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

sedコマンドのスクリプトのコメントについて、#の記号が利用できます。

script.sed

行の後の行にテキストを追記
(aコマンド)

aコマンドは行の後の行にテキストを追記することができます。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

複数行のテキストを追記する場合は以下のようにします。

コマンド例

script.sed

実行結果(一部省略) ▼表示

行の前の行にテキストを追記
(iコマンド)

iコマンドは行の前の行にテキストを追記することができます。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

また、複数行のテキストを追記する場合は以下のようにします。

コマンド例

script.sed

実行結果(一部省略) ▼表示

アドレスについて

スクリプトは

で表現されます。
addr:行の位置や範囲を示すもので、行番号や正規表現を用いて指定できます。
X:sedコマンドの機能を決定する、一文字のことです。
options:Xで指定したものによって必要なオプションのことです。

ここでは、addr、つまりアドレスの指定方法についていくつか紹介します。

アドレスを指定しない

アドレスを指定しない場合、すべての行に対してコマンドを実行します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

数字で指定
(num)

コマンドの前に数字を記述するとその行番号の行に対して、コマンドを実行します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

範囲で指定
(num,num)

アドレスを範囲で指定する場合は2つの数字をカンマで区切ります。
コマンド例では1から5行目に対して、コマンドを実行することができます。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

最終行を指定
($)

最終行を指定する場合、$記号で指定することができます。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

最初の行を指定する場合は、数字で1を指定することで最初の行を指定することができます。

正規表現で指定
(/regexp/または\%regexp%等)

正規表現でアドレスを指定します。
例えば、コマンド例ではappleという単語が含まれている行に対して、コマンドを実行します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

正規表現で指定する場合、「/」の記号で囲むほかに「\」と「%」等のような一文字の記号を組み合わせても正規表現を行うことができます。

別の記号を用いて正規表現を用いると場合によって、エスケープシーケンスを使うことを減らすことができます。

別の記号を用いた場合のscript.sedの例1

別の記号を用いた場合のscript.sedの例2

別の記号を用いた場合のscript.sedの例3(非推奨)

最後の例は一応アルファベットなどの記号も利用できるという例で、どこまでが区切りであるかがわかりにくいため、使用することを推奨しません。

正規表現で範囲を指定
(num,/regexp/)

アドレスの範囲は数字と正規表現を組み合わせることでも作ることができます。
また、数字と正規表現で範囲を作る際、0という数字を使うことができます。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

0,/regexp/1,/regexp/は微妙に意味が違います。

0,/regexp/の場合

コマンド例

script.sed

実行結果 ▼表示

1,/regexp/の場合

コマンド例

script.sed

実行結果 ▼表示

これは、0,/regexp/の場合、「apple apple apple」という行が範囲の終了を表す/regexp/にマッチするため、itemtext.txtの最初の行の「apple apple apple」にマッチした時点で範囲が終了します。

しかし、1,/regexp/の場合はitemtext.txtの最初の行の「apple apple apple」が範囲の開始を表す1の方にマッチするため、範囲の終了を表すitemtext.txtの2つ目の「apple apple apple」という行が登場するまで、コマンドの実行が行われます。

このような点で0,/regexp/1,/regexp/は異なります。