この章では,ed
と同じ機能を持ったプログラムである
sed
ストリーム・エディタについて説明します。
この章で説明されている操作を行うために,ed
ライン・エディタの使用方法を知っている必要はありません。
次の各節で,sed
エディタについて説明します。
ed
と異なる点は,sed
はユーザと対話するのではなく,スクリプトと呼ばれるコマンド・リストを使用してファイルの編集を行う点です。
このような編集形式をとるため,sed
は次のような作業に最適です。
サイズの大きいファイルを編集する。
長時間にわたるタイプ入力の繰り返しやカーソルの移動をすることなく,複雑な編集操作を何度も実行する。
1 度の入力でグローバルな変更を行う。
sed
ストリーム・エディタは,標準入力または指定したファイルから入力を受け取り,コマンド・ファイルまたはコマンド行のコマンドによって入力を変更し,その結果のストリームを標準出力に書き込みます。
2 つ以上の入力ファイルを指定すると,sed
は,各ファイルを順番に処理して,その結果を標準出力に連結します。
コマンド・ファイルを指定せずに,sed
コマンドオプションも使用しなかった場合,sed
は,標準入力を変更せず標準出力にコピーします。
このエディタは,編集中のファイルの 2,3 行をメモリに保持するだけなので,一時ファイルを使用しません。
したがって,編集されるファイルのサイズは,使用可能なディスク・スペースによってだけ制限されます。
sed
で使用するコマンド・スクリプトは,エディタを実行する前に作成しておいたファイルでも,また,コマンド・オプションとして入力した一連のコマンドでも,またはその両方でもかまいません。
エディタは,1 回の呼び出しで 99 個までのコマンドしか処理することができません。
このような制約のため,また,かなり複雑な編集作業を実行するために,
sed
からの出力を
sed
の別のインスタンス
にパイプする必要が生じることがあります。
3.2 sed エディタの実行
sed
[
[-n
]
]
[
[
[-e
]
]
[script
]
]
[
[-f script_file
]
]
[
[source_file1
]
[
[source-file2...
]
]
]
表 3-1
に,sed
コマンドのフラグを示します。
表 3-1: sed コマンドのフラグ
フラグ | 説明 |
-e
script |
文字列スクリプトで指定された編集コマンドを,編集コマンドのスクリプトの終わりに追加する。-e
フラグを 1 つだけ使用し,-f
フラグを指定しない場合は,-e
フラグを省略すると,1 つの
script
をコマンド行に
sed
の引数として指定することが可能。 |
-f
script_file |
script_file を編集スクリプトのソースとして使用する。script_file は,入力に適用される編集コマンドの集合。 |
-n |
通常では標準出力へ書き込まれる情報を抑制する。 |
-e
および
-f
オプションの表記順は重要です。
通常,sed
を実行する前に,必要な編集コマンドを記述したコマンド・ファイルを作成します。sed
エディタのコマンド・セットは強力で,ほとんど入力の必要はありません。
コマンド・ファイル内の各コマンドは,個別の行に入力することも,セミコロン ( ;
) を使用して各コマンドを区切り,複数のコマンドを 1 行にタイプすることもできます。
たとえば,次の 2 つのスクリプトは,いずれも
.ne
,.RE
,または
.RS
で始まるすべての行を削除します。
スクリプト 1:
/^\.ne/d /^\.R[ES]/d
スクリプト 2:
/^\.ne/d;/^\.R[ES]/d
コマンド・ファイル (次の例では
cmdfile
) を作成した後,次の例のように
sed
コマンドを入力します。
$ sed -f cmdfile infile > outfile
このコマンドは,cmdfile
に含まれているコマンドを使用して,infile
を編集し,出力を
outfile
に書き込みます。
入力ファイルは変更されません。
短い編集スクリプトの場合には,-e
オプションの引数として編集コマンドをコマンド行に入力しても同じジョブを実行できます。
$ sed -e '/^\.ne/d;/^\.R[ES]/d' infile > outfile
同一のコマンド行で
-e
オプションと
-f
オプションを同時に使用すると,両方のオプションで指定されたすべてのコマンドが実行されます。
実行される順番は,オプションがコマンド行に指定されている順番です。
次に例を示します。
$ echo "s/line/foo/" > sedx $ echo "Test line" | sed -f sedx -e 's/line/bar/' Test foo $ echo "Test line" | sed -e 's/line/bar/' -f sedx Test bar
たとえば,次のように,1 個の
sed
コマンドに
-e
オプションと
-f
オプションを 2 回以上使用することができます。
$ sed -f script1 -e 's/foo/bar/' -f script2 msgs > msgs2
sed
を実行すると,このエディタは構文のチェックおよび効率をよくするためのコマンドの編成を行いながら,コマンド・スクリプトを読み込んでコンパイルします。
その後,入力ファイルを 1 行ずつパターン・スペースというメモリ領域に読み込みます。
次に,エディタはスクリプトに記述してあるコマンドで指定されたアドレスを,パターン・スペースの行に対して次々に照合させます。
コマンドのアドレスがパターン・スペース内の 1 行または複数行と照合した場合,sed
は必ず照合したテキストにその編集コマンドを実行します。
各コマンドはテキストに対して順番に実行されます。
各コマンドで変更した結果は,後続するコマンドの入力として使用されます。
パターン・スペース内の所定の行がそれ以上コマンドと照合しなくなると,sed
は出力にその行を書き込み,次の入力を読み込みます。
この処理は繰り返し行われます。
この動作の順序のフローチャートは,図 3-1
のとおりです。sed
の動作は,図 2-1
に記載した
awk
プログラムの動作と非常によく似ています。
図 3-1: sed 処理の順序
編集コマンドによっては,エディタに他のスクリプト・コマンドをバイパスさせたり,または (それらを削除させることで) ある行の書き込みを禁止させたり,または処理を中断させたりして,編集処理の動作方法を変更するものがあります。
3.3 編集行の選択
sed
エディタは,アドレスの照合によって編集する行を識別します。
アドレスは,行番号でもコンテキスト・アドレスでもかまいません。
行番号
入力ストリームの開始行は 1 行目になります。
ライン・カウンタは後続する各行ごとに 1 ずつ増分します。
ドル記号 ($) は,入力ストリームの最終行を指定するための略字です。
1 回の
sed
の呼び出しで 2 つ以上のファイルを編集する場合,ライン・カウンタは編集されたすべてのファイルの行数を加算していきます。
たとえば,最初のファイルが 100 行の場合は,2 番目のファイルの開始行は 101 行目となります。
コンテキスト・アドレスは,パターン・デミリタ (通常はスラッシュ) で囲まれた正規表現です。
たとえば
/^\.R[ES]/
は,.RE
または
.RS
で始まるすべての行と照合します。
パターン・デリミタとしてスラッシュ以外の文字を使用したい場合は,最初に使用する際にその文字の前にバックスラッシュを付けることによって可能になります。 たとえば,次の 2 つのパターンは同じものとして解釈されます。
/abc/ \xabcx
2 つ目のパターンでは,パターン・デミリタとして
x
を使用しています。
パターン・デミリタとして使用している文字をリテラル文字として使用したい場合には,前にバックスラッシュを付けます。
たとえば,\x\xyzx
は,文字列 xyz と解釈されます。
sed
エディタは,第 1 章で説明した基本正規表現に加えて,表 3-2
に示す正規表現も認識します。
表 3-2: sed で認識される正規表現
正規表現 | 名称 | 規則 |
\n |
改行 | 埋め込まれた改行文字を照合します。 |
// | 空のパターン・デミリタ | 直前に指定された正規表現と一致したテキストを照合します。 |
sed
コマンドのなかには,アドレスを受け入れないものがあります。
アドレスを受け入れるコマンドは,指定されるアドレスの数によって次のように異なった動作をします。
アドレスが指定されなかった場合,そのコマンドは入力ストリームのすべての行に対して実行されます。
1 つのアドレスが指定された場合は,コマンドはそのアドレスと照合する各行に対して実行されます。
2 つのアドレスが指定された場合,最初のアドレスが照合する行から 2 番目のアドレスが照合する行までのすべての行に対してコマンドが実行されます。 その後で,対象となる別の範囲を見つけるために,エディタは再び最初のアドレスでの照合を行います。
注意
2 つのアドレスが指定された場合に,
sed
が終わりのアドレスと照合する行を見つけられないと,sed
はファイルの最初のアドレスからファイルの最後までのすべての行に対して実行されます。
各
sed
コマンドは,オプションのアドレスを持つ 1 文字の英字で構成されています。
コマンドのなかには,引数を必要とし,コマンドの動作を変更させる修飾子を受け入れるものがあります。
アドレスと英字の間には,スペースを入れてはなりません。
1 つのコマンドに 2 つのアドレスを使用する場合は,コンマでアドレスを区切ってください。r
コマンドと
w
コマンド,および,s
コマンド用の
w
フラグを使用する場合は,英字と引数の間にスペースが 1 つ必要です。
それ以外では,英字と引数の間にスペースを入れてはなりません。
表 3-3,表 3-4,および
表 3-5
では,個々の
sed
コマンドについて説明し,それぞれの構文を記述します。
これらの表については,次の規約が適用されます。
行範囲という用語は,コマンドに与えられたアドレスの数で指定される 1 行,複数行,またはすべての行を意味します。
大カッコ
[ ]
はオプション要素を囲みます。
ネストした大カッコは,大カッコで囲まれた要素が存在する場合のみネストした要素を使用できることを表します。
イタリック体 (斜体) は,指定する対象の一般名を示します。 たとえば file は,コマンド引数としてファイル名を使用することを表します。
すべてのオプションの要素を含む
s
コマンドの例を次に示します。
1,/^$/s/vizier//g
この例は,メール・メッセージのヘッダ (1 行目から最初に出現する空白行まで) を処理します。
指定された範囲内の文字列
vizier
をすべて削除します。
表 3-3
はテキスト編集および移動の
sed
コマンドについて説明し,構文を示します。
表 3-3: テキスト編集および移動のコマンド
コマンド | 説明 |
テキストの追加 | |
[addr1]a\
text[\
text...] |
addr1
で指定された行の後ろに,指定されたテキスト
[脚注 2]
を書き込んで出力する。i
コマンドを参照。
|
行の変更 | |
[addr1
[,addr2
]]c\
text[\
text...] |
アドレスで指定された行範囲を削除して,指定されたテキスト [脚注 2] を,削除された所に書き込んで出力する。 [脚注 3] |
行の削除 | |
[addr1
[,addr2
]]d |
指定された行範囲を削除する。 [脚注 3] |
パターン・スペースの最初の行の削除 | |
[addr1
[,addr2
]]D |
最初の改行文字が表れるまでのパターン・スペースのすべてのテキストを,その改行文字を含めて削除する。 パターン・スペースに 1 行しかない場合は,このコマンドにより別の行が入力からパターン・スペースに読み込まれる。 これらの動作の後で,このコマンドは編集コマンドのリスト全体を先頭から再開する。 |
行の挿入 | |
[addr1
]i\
text[\
text...] |
指定されたテキスト
[脚注 2]
を,addr1
で指定された行の前に書き込んで出力する。a
コマンドを参照。 |
次の行の読み込み | |
[addr1
[,addr2
]]n |
パターン・スペースの中の,指定された範囲を (削除されていなければ) 書き込んで出力する。 次に,入力から次の行をパターン・スペースに読み込む。 |
行の結合 | |
[addr1
[,addr2
]]N |
指定された複数の行を,埋め込まれた改行文字を持つ 1 行となるように結合させる。
アドレスが 1 つしか与えられていない場合,このコマンドは指定された行を入力ストリームの次の行と結合する。
アドレスの指定,または文字列置換のためのパターン照合は,埋め込まれた改行文字をまたがって拡張することができる。
照合用に埋め込まれた改行文字を示すには, |
行の表示 | |
[addr1
[,addr2
]]p |
編集処理の実行中に
p
コマンドが出現した時点で,指定された行範囲を出力に書き込む。
このコマンドは,ファイルのセクションを並べ換えるために使用できる。 |
パターン・スペースの開始行の表示 | |
[addr1
[,addr2
]]P |
編集処理の実行中に
P
コマンドが出現した時点で,最初の改行文字が出現するまでのパターン・スペースのすべてのテキストの内容を,その改行文字を含めて出力へ書き込む。 |
ファイルの読み込みと追加 | |
|
指定されたファイル [脚注 4] を読み込んで,そのファイルの内容を addr1 に続けて出力へ書き込む。 |
テキストの置換 | |
[addr1
[,addr2
]]s/expr
/string
/[flags
] |
|
指定された行の中から,expr
で定義した正規表現と照合する文字列を見つけ出し,その文字列を
string
と置換する。
このコマンドの動作は,g ,p ,および
w
の
file
フラグで修飾される。expr
または
string
にスラッシュ ( / ) が入っている場合は,バックスラッシュ (s/path/path\/file/ ) を使用して,文字としてのスラッシュを避ける必要がある。
あるいは,アット符号 ( @ ) または疑問符 ( ? ) などの別のデリミタを使用する。
たとえば,s@path@path/file@
は,path
を
path/file
に置換する。
[脚注 5]
|
|
指定したファイルへの書き込み | |
[addr1
[,addr2
]]w file |
編集処理の実行中に,w
コマンドが出現した時点で指定された行範囲を指定されたファイル
[脚注 6]
に書き込む。 |
行番号の表示 | |
[addr1
]= |
指定された行の行番号を出力に書き込む。 |
表 3-4
はバッファ操作用の
sed
コマンドについて説明し,構文を示します。
コマンド | 説明 |
ホールド・エリアからのテキストの取り出し | |
|
ホールド・エリアの内容が存在する場合は,その内容を
addr1
と
addr2
で指定されたパターン・スペースにコピーする。g
コマンドは,パターン・スペースの以前の内容を破壊する。G
コマンドは,ホールドされたテキストをパターン・スペースの内容に追加する。
改行文字を使用して,以前のテキストと追加されたテキストを分割する。 |
ホールド・エリアへのテキストの移動 | |
|
パターン・スペースの指定された範囲をホールド・エリアにコピーする。h
コマンドは,ホールド・エリアの以前の内容を破壊する。H
コマンドは,パターン・スペースのテキストを,ホールド・エリアの内容に追加する。
改行文字を使用して,以前のテキストと追加されたテキストを分割する。 |
パターン・スペースとホールド・エリアの交換 | |
[addr1
[,addr2
]]x |
パターン・スペースの内容とホールド・エリアの内容を交換する。 |
表 3-5
はフロー制御の
sed
コマンドについて説明し,構文を示します。
コマンド | 説明 |
範囲の否定(「以外」) | |
[addr1
[,addr2
]]!cmd |
感嘆符 ( ! ) を指定することによって,sed
は,入力ファイルの
addr1
と
addr2
で指定された範囲以外の部分に対して,感嘆符に続くコマンドを実行する。 |
コマンドのグループ化 | |
|
左右の中カッコによって,実行するコマンドのグループを囲む。 このコマンドのグループは,addr1 と addr2 で指定された範囲に対して,1 つのセットとして適用される。 最初のコマンドは,この表で示されているように,左の中カッコの次の行にあってもよいし,中カッコと同じ行にあってもよい。 右の中カッコは 1 行に単独で書かなければならない。 グループは他のグループ内にネストすることができる。 |
ラベル | |
:label |
分岐コマンドの宛先として使用される,編集コマンドのストリーム内の任意の場所を定義する。
ラベルは最高 8 バイトまでの文字列である。
編集ストリームの各ラベルは,独自のものでなければならない。
詳細は,
sed (1) |
分岐 | |
blabel |
label
に指定された編集スクリプトの特定の場所に分岐し,ラベルの次のコマンドを使用して,現在の入力行の処理を続行する。label
が省略されている場合は,b
コマンドは残りの編集スクリプトをバイパスし,新しい入力行を読み込み,スクリプトの先頭から編集を開始する。 |
条件付き分岐 | |
tlabel |
現在の入力行で,置換が正常終了した場合に,label
へ分岐する。
それ以外は,コマンドは分岐しない。
どちらの場合でも,このコマンドにより,置換が実行されたことを示すフラグがクリアされる。
このフラグは,個々の新しい入力行の開始時点でもクリアされる。label
が省略されていて,分岐が必要とされる場合は,t
コマンドは残りの編集スクリプトをバイパスし,新しい入力行を読み込み,スクリプトの先頭から編集を開始する。 |
終了 | |
[addr1
]q |
現在の行を出力に書き込み,追加されたまたは読み込まれたテキストを出力に書き込んでから終了する,という規則正しい順で編集を終了する。 |
s
コマンドは,入力ファイルの指定された行で文字列を置換します。
エディタは正規表現の
expr
を満たしている入力ファイルの文字列を見つけた場合は,その文字列を
string
で指定された文字セットと置換します。string
引数は正規表現ではなく,走査されることも解釈されることもありません。
ただし,次のような例外があります。
string
の中のすべてのバックスラッシュ文字 ( \
) をエスケープしなければならない。
string
の中のスラッシュ文字 ( /
) の取り扱いについては,表 3-3
の説明を参照。
次の 2 つの特殊記号を,string の中で使用することができる。
string
内のこの記号は,入力行の中の
expr
と照合した文字列自身と交換されます。
たとえば,s/[Bb]oy/&s/
というコマンドを次の行に実行するとします。
The boy watched the game.
このコマンドは,入力行の中から
Boy
または
boy
のいずれかを見つけ出し,いずれを見つけた場合にも,s を追加して出力にコピーするように
sed
に指示します。
このコマンドは
boy
を見つけたので,その文字列を変更して出力に移します。
この結果は次のとおりです。
The boys watched the game.
数値
n
は 1 桁の数字です。string
内のこのシンボルは,expr
の中の
n
番目のサブ正規表現と一致する入力行の文字列と置換されます。
サブ正規表現は,バックスラッシュとカッコ (\(
および
\)
) によって区切られます。
たとえば,コマンド
s/\(stu\)\(dy\)/\1r\2/
を次の行に適用する場合を考えてみましょう。
The study chair.
このコマンドは,入力行の中から
study
を見つけて,中間に r を挿入して,そのパターンを出力にコピーするように
sed
に指示します。
この結果は次のとおりです。
The sturdy chair.
フラグを使用して,s
コマンドの動作を次のように変更することができます。
通常,各行の範囲の中で,最初に照合した文字列だけが置換されるが,g
(グローバル) フラグを使用すれば,sed
はその範囲内のすべての行に対して,すべての照合した文字列を置換する。
照合する文字列が同一である必要はない。
正規表現
expr
は,すべての可能な照合に対して,毎回評価される。
p
(プリント) フラグは,置換を実行した後に必ず指定された行を明示的に書き込むように
sed
に指示する。
この書き込みは,sed
の通常の動作を補足する。
w file
(書き込み) フラグは,置換を実行した後に必ず指定された行を指定したファイルに書き込むように
sed
に指示する。
w
フラグとファイル名の間には,1 つのスペースを入れなければならない。
これらのフラグは,1 度の
s
コマンドで使用できます。
組み合わせる場合には,w
フラグは,指定するすべてのフラグの最後のフラグとして指定されなければなりません。