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

sedコマンドは主にテキストを置換することに使われます。
また、テキストを置換する際に、正規表現のグループ化を用いることができれば、より複雑にテキストを置換することができます。

sedとは

sedとはストリームエディタ(stream editor)の略で、入力ファイルやパイプラインで渡されたテキストを編集することができます。

普通のエディタと違い、パイプライン渡されたテキストを編集できることが特徴です。
また、ファイルにある特定の文字列を一括に編集できるのも利点といえるでしょう。

sedコマンドの構文

sedコマンドの構文

オプション:
sedコマンドに対するオプションです。

スクリプト:

で表現されます。また、スクリプトは以下のように記述することができます。

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

入力ファイル:
1個以上の入力ファイルを指定できます。

sedコマンドに入力ファイルがないもしくは-(ハイフン)の場合は、標準出力に対して、sedコマンドのスクリプトを実行します。

上から順に
1つ目は入力がファイルがない場合です。
2つ目は-(ハイフン)を用いた場合です。
3つ目はリダイレクトによって、ファイルを標準入力としてsedコマンドに渡した場合です。

それぞれsedコマンドで、標準出力に対して処理を行うという意味で同じになります。

コマンド例の想定

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

itemtext.txt ▼表示

sedコマンドのファイルの保存方法について

sedコマンドの出力は、オプションがない場合、標準出力に現れます。
また、sedコマンドの-iオプションをつけた場合、対象のファイルに対して出力を行います。

ファイルに保存する方法として、一つは、リダイレクトを利用して別のファイルを作成し、その後にmvコマンドなどでtmp.txtをitemtext.txtに置き換える方法があります。

また、-iオプションを用いて、直接ファイルを置き換えてしまう方法があります。

-iオプションは、GNU sedで利用できます。

-iオプションは、実際には一時ファイルが作られ、その一時ファイルに対してsedコマンドの出力が行われ、その一時ファイルの名前を対象のファイルとして置き換えます。

-iオプションで置き換える前のバックアップファイルが欲しい場合は、

のように-iオプションの後に接尾辞を指定することでバックアップファイルを作成することができます。

この例ではitemtext.txt.bakのような置き換える前のバックアップファイルを作成することができます。

パターンマッチした文字列を別の文字列に変換
(s/regexp/replacement/flags)

s/regexp/replacement/flagsは、sedコマンドの主要な機能といえるものです。

正規表現(Regular Expression)regexpにマッチしたものを別の文字列replacementに置き換えます。
また、flagsは0個以上を指定することでき、flagsによって文字列の置き換え方などを変更することができます。

最初にパターンマッチした文字列を置換
(flags:なし)

s/regexp/replacement/は、それぞれの行で最初に登場した文字列を別の文字列に置き換えます。
コマンド例では、最初に登場したappleという文字列をmelonという文字列に置き換えます。

コマンド例

itemtext.txt ▼表示

実行結果 ▼表示

それぞれの行に現れるappleをすべて置き換えるわけではないので注意が必要です。

すべてのパターンマッチした文字列を置換
(flags:g)

s/regexp/replacement/gはそれぞれの行に登場するすべての正規表現にマッチした文字列を別の文字列に置き換えることができます。
コマンド例では、行に登場したすべてのappleをmelonに置き換えます。

コマンド例

itemtext.txt ▼表示

実行結果 ▼表示

n番目のパターンマッチした文字列を置換
(flags:数字)

s/regexp/replacement/1等のflagsに数字を入れたものは、n番目に登場したものだけを別の文字列に変更することができます。
コマンド例では、2番目に登場したスペースを:に変更しています。

コマンド例

itemtext.txt ▼表示

実行結果 ▼表示

1番目のスペースを,に2番目に登場したスペースを:に変更する場合は以下のようにします。

コマンド例

実行結果 ▼表示


-eオプションは、追加のスクリプトを記述することで変更することができます。
-eオプションは記述された順番に処理されます。

この例では、最初の-eオプションのスクリプトで1番目のスペースが,に変更されます。
その次に変更された状態のテキストで、次の-eオプションのスクリプトで1番目のスペース(元ファイルの2番目のスペース)を:に変更しています。

また、追加のスクリプトを記述する方法として;を用いて記述する方法もあります。以下のコマンド例でも上と同様の実行結果を得ることができます。

コマンド例

別の文字列に置換された行を表示
(オプション:-n, flags:p)

pフラグは変更があった行のみを表示します。
-nオプションは、スクリプトで明示的に表示する行を除き、sedコマンドで出力する行を表示しないようにします。

コマンド例

itemtext.txt ▼表示

実行結果 ▼表示

ここで、-nオプションをつけない場合は、変更があった個所だけが重複して表示されてしまうことに注意が必要です。

コマンド例

実行結果 ▼表示

別の文字列に置換された行をファイルに出力
(flags:w filename)

wフラグはファイル名を指定することでそのファイルに変更があった行を書き込みます。
また、ファイルがない場合は作成され、ある場合は上書きされます。

変更があった行を別のファイルに保存したい場合に用いることができます。

コマンド例

itemtext.txt ▼表示

実行結果(標準出力) ▼表示

実行結果(change.txt) ▼表示

グループ化を用いて置換文字列にパターンマッチした文字列を使用

グループ化とは、正規表現の特徴の一つでグループ化したパターンをキャプチャして、置換文字列で使うことができます。

コマンド例では、それぞれの行に対して、最初の単語を最後の単語として追記します。

例えば、「apple onion yuzu」なら、最初の単語の「apple」をその行の最後に追記して「apple onion yuzu apple」にします。

コマンド例

itemtext.txt ▼表示

実行結果 ▼表示

sedコマンドでの正規表現のグループ化は「\(」と「\)」で囲むことで行うことができ、その後に「\1」、「\2」のように呼び出すことができます。

呼び出す数字に関して、「\(」が現れる順番
で1から保存されます。
この例では、最初の外側にある「\(」と「\)」は行の全体を表し「\1」で呼び出すことができます。
次の内側にある「\(」と「\)」は最初の単語を表し「\2」で呼び出すことができます。
つまり、この例のパターンは行全体を表して、行全体が置き換える対象になっています。
そして、sedコマンドで行全体を書き換えるようなイメージになっています。
「[^ ]」はスペース以外の文字を表し、「*」は直前の文字の0回以上繰り返しを示す記号になります。