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

sedコマンドはパターンスペースとホールドスペースという2つのバッファがあります。
これらのバッファを用いることで、より複雑なテキスト処理を行うことができます。

また、sedコマンドにも条件分岐の処理を行うことができます。
条件分岐の処理を使いこなすことができれば、sedコマンドの置換コマンドであるsコマンドをよりうまく使うことができます。

最後に、sedコマンドは複数行の処理を行うこともできます。
これは、連続する複数行を一つの行にまとめる事ができ、条件分岐の処理等を利用するとさらに高度な処理を行うことができます。

コマンド例の想定

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

itemtext.txt ▼表示

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

ホールドスペースの利用

sedコマンドでは、現在編集中の行をそれ以降の行でも使用したい場合にホールドスペースが利用できます。
しかし、ホールドスペースというバッファは一つしか利用できないので、注意が必要です。

パターンスペースをホールドスペースへ
(hコマンド)

hコマンドは、パターンスペースの内容をホールドスペースにコピーできます。
コピーする際、ホールドスペースが保存していた内容は削除されます。

ホールドスペースに何かを保存した場合、gコマンド等でパターンスペースに呼び戻さないとホールドスペースの内容を使うことができません。
コマンド例は次のgコマンドを参照してください。

ホールドスペースをパターンスペースへ
(gコマンド)

gコマンドは、ホールドスペースの内容をパターンスペースにコピーできます。
コピーする際、パターンスペースが保存していた内容は削除されます。

コマンド例は、最初の1行目の内容をホールドスペースに保存します。
そして、それ以降の行の「onion onion onion」にマッチングした行で、そのマッチングした行の内容を表示した後に、ホールドスペースの内容を表示します。

コマンド例

itemtext.txt ▼表示

script.sed

実行結果

script.sedの3行目のコマンドのグループ化を利用しました。
なぜなら、コマンドを別々にした場合、うまく動作しませんでした。
コマンド例

script.sed

実行結果

アドレスでの正規表現はパターンスペースの内容を参照して、マッチングを行っているかもしれません。
なので、アドレスでの正規表現を用いる場合は、コマンドのグループ化を用いて呼び出したほうが良いと思います。

パターンスペースをホールドスペースへ追記
(Hコマンド)

Hコマンドは、ホールドスペースの内容をパターンスペースに追記することができます。
追記する際に、現在のホールドスペースの内容に改行を入れます。

コマンド例は、1行目の内容をホールドスペースに保存し、2行目の内容をホールドスペースに追記します。
その後に、それ以降の行の「onion onion onion」にマッチングした行で、そのマッチングした行の内容を表示した後に、ホールドスペースの内容を表示します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果

ホールドスペースをパターンスペースへ追記
(Gコマンド)

Gコマンドは、ホールドスペースの内容をパターンスペースに追記することができます。
追記する際に、現在のパターンスペースの内容に改行を入れます。

コマンド例は、1行目の内容をホールドスペースに保存します。
その後に、それ以降の行の「onion onion onion」にマッチングした行で、ホールドスペースの内容をパターンスペースに追記して、表示します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果

パターンスペースとホールドスペースを交換
(xコマンド)

xコマンドは、パターンスペースの内容とホールドスペースの内容を入れ替えることができます。

コマンド例では、1行目の内容をホールドスペースに保存します。
その後に、それ以降の行の「onion onion onion」にマッチングした行で、パターンスペースの内容とホールドスペースの内容を入れ替え、表示します。
さらに、もう一度、パターンスペースの内容とホールドスペースの内容を入れ替えて、表示します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果

条件分岐処理

ラベル

sedコマンドのスクリプトは、プログラミングのgoto文のようにスクリプトのコマンドのどこかにラベルをつけることができます。
ラベルは:markや:labelのように、:と文字列でつけることができます。

このラベルは、bコマンドやtコマンド等で使用することができます。
ラベルの付け方は以下のようになります。

script.sed

無条件分岐
(bコマンド)

bコマンドは、無条件分岐のコマンドで、bコマンドで指定したラベルにジャンプします。
また、bコマンドにラベルが何も指定していない場合、次のサイクルに移行します。

コマンド例では、初めにappleのある行が削除され、それ以外の行が表示されます。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

条件分岐
(tコマンド)

tコマンドは、入力行が置換に成功していた場合、つまり、sコマンドが成功していた場合にラベルにジャンプします。

tコマンドの条件が成り立つときにラベルが何も指定していない場合、次のサイクルに移行します。

コマンド例は、appleの単語をすべて削除する例です。
また、簡単な整形処理も行っています。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果 ▼表示

逆に置換に成功していない場合、ラベルにジャンプするTコマンドもあります。

マルチライン処理

パターンスペースに次の入力行を追記
(Nコマンド)

Nコマンドは、パターンスペースに改行を追加し次の入力行を追記します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果

パターンスペースの最初の改行まで表示(Pコマンド)

Pコマンドは、パターンスペースの最初の改行までを表示します。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果

パターンスペースの行を1行削除し、次のサイクルを実行
(Dコマンド)

Dコマンドは、改行までの行を1行削除して、残りのパターンスペースを残したまま次のサイクルを実行します。

コマンド例は、行の最後の単語と次の行の最初の単語が同じ場合は、くっつけるようなイメージの例です。

コマンド例

script.sed

itemtext.txt ▼表示

実行結果

参考

外部リンクgnu sedマニュアル(英文)