2 行編集入門 ¶
ed は、Unix オペレーティングシステムとともに Ken Thompson と Dennis Ritchie が作りました。これは、より複雑でプログラム可能な前身の QED を洗練したものです。Thompson と Ritchie は QED にすでにパターン照合機能を追加していました(正規表現を参照)。
このチュートリアルでは、Unix シェル sh と Unix のファイルシステムに関する実用的な知識があることを推奨します。ed はこれらと密接に連携するよう設計されているためです。(bash の詳細はbash マニュアルを参照してください。)
行エディターと画面エディターの主な違いは、画面エディターではユーザーのコマンドに即座に反応が返るのに対し、行エディターでは結果が見えるまでに長い入力が必要なことがある点です。即座に反応が返る利点は、もちろん、間違えたときに被害が広がる前にすぐ修正できることです。ed での編集には、より多くの戦略と事前の検討が必要ですが、使いこなせば非常に効率的になります。
ed のコマンド構文の多くは、ほかの Unix ユーティリティーと共通しています。
シェルと同様に、RETURN(復帰キー)で入力行を確定します。そのため、ed でコマンドやテキストを「入力する」と述べるときは、各行の末尾で RETURN を押すことを意味します。RETURN を押す前なら、BACKSPACE で直前の文字を消すか、CONTROL-u(CONTROL キーを押しながら u を入力)で行全体を消して、入力を修正できます。
ed は起動すると指示を待ちますが、シェルのようにはプロンプトを表示しません。そこでまず、ed に P(prompt)コマンドを与えて、表示させましょう。
$ ed P *
既定では、ed はコマンドプロンプトにアスタリスク(「*」)を使い、シェルのコマンドプロンプト(「$」)との混同を避けます。
Unix シェル(sh)のコマンドに !(感嘆符、別名 bang)を前置すると、ed の中から実行できます。たとえば次のとおりです。
*!date Mon Jun 26 10:08:41 PDT 2006 ! *!for s in hello world; do echo $s; done hello world ! *
ここまでは Unix シェルでコマンドを実行するのと変わりません。しかし、コマンドの出力を編集したり、ファイルに保存したりしたいとします。まず、ed がアクセスできるバッファーと呼ばれる一時的な場所に、コマンドの出力を取り込む必要があります。これには ed の r コマンド(read と覚えます)を使います。
*r !cal -m 137 *
ここで ed は、137文字をエディターのバッファーに読み込んだと知らせています。これは、簡単な ASCII のカレンダーを表示する cal コマンドの出力です。バッファーの内容を表示するには、p(print)コマンドを使います(大文字のプロンプトコマンドと混同しないでください)。表示する行の範囲を示すために、コマンドの前に ,(コンマ)を付けます。これは「バッファー全体」の略記です。
*,p
June 2006
Mo Tu We Th Fr Sa Su
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
*
次に、w(write)コマンドで、バッファーの内容を「junk」というファイルに書き込みましょう。
*w junk 137 *
言うまでもありませんが、バッファーの内容はこまめに書き込むのがよい習慣です。ed を終了すると、書き込んでいないバッファーの変更は失われるためです。
以下の操作例では、ed による行編集の基本的な概念を示します。まず、シェイクスピアの助けを借りて sonnet というファイルを作ります。シェルと同様に、ed へのすべての入力の後には改行文字が必要です。「#」で始まるコマンドはコメントとして扱われ、無視されます。入力モードでは「#」で始まる行も通常の入力です。
$ ed # 'a' コマンドはエディターのバッファーにテキストを追加します。 a No more be grieved at that which thou hast done. Roses have thorns, and filvers foutians mud. Clouds and eclipses stain both moon and sun, And loathsome canker lives in sweetest bud. . # 1行にピリオドを1つだけ入力すると、edはコマンドモードに戻ります。 # 次に、バッファーをファイル sonnet に書き込んで終了します: w sonnet 183 #edは書き込んだ文字数を報告します。 q $ ls -l total 2 -rw-rw-r-- 1 alm 183 Nov 10 01:16 sonnet $
次の例では、ファイル sonnet の誤字を修正します。
$ ed sonnet 183 # まず「p」コマンドでバッファーを端末に表示します。 # ',' は「すべての行」を意味します。 ,p No more be grieved at that which thou hast done. Roses have thorns, and filvers foutians mud. Clouds and eclipses stain both moon and sun, And loathsome canker lives in sweetest bud. # 編集する行として2行目を選択します。 2 Roses have thorns, and filvers foutians mud. # 置換コマンド「s」で 'filvers' を 'silver' に置き換え、 # 結果を表示します。 s/filvers/silver/p Roses have thorns, and silver foutians mud. # 続いて 'fountains' のつづりを修正します。 s/utia/untai/p Roses have thorns, and silver fountains mud. w sonnet 183 q $
ed は行指向なので、編集する行または行の範囲を指定する必要があります。上の例では、行番号、つまりバッファー内での順番によって指定しています。代わりに、「/filvers/」のように行内の一意な文字列でも指定できました。この場合「/」で目的の文字列を囲みます。その後のコマンドは、選択した行、すなわち現在行だけに作用します。その行の一部を置き換えるには、「s/old/new/」という構文の置換コマンドを使います。
ed が受け付けるコマンドは1行につき1つだけですが、表示コマンド「p」は例外で、ほとんどのコマンドの末尾に付けられます。
次の例では、ソネットに題名を追加します。
$ ed sonnet 183 a Sonnet #50 . ,p No more be grieved at that which thou hast done. Roses have thorns, and silver fountains mud. Clouds and eclipses stain both moon and sun, And loathsome canker lives in sweetest bud. Sonnet #50 # 題名は末尾に追加されました。「最初の行の前」に追加するには、 # '0a' を使うべきでした。 # 題名を正しい位置へ移動します。 5m0p Sonnet #50 # 題名が最初の行になり、現在アドレスも # この行のアドレスに設定されました。 ,p Sonnet #50 No more be grieved at that which thou hast done. Roses have thorns, and silver fountains mud. Clouds and eclipses stain both moon and sun, And loathsome canker lives in sweetest bud. wq sonnet 195 $
ed がファイルを開くと、現在アドレスは最初にそのファイルの最終行のアドレスに設定されます。同様に、移動コマンド「m」は、移動した最後の行のアドレスを現在アドレスに設定します。
関連するプログラムやルーチンは vi(1)、sed(1)、regex(3)、sh(1) です。関連文書は次のとおりです。
Unix User’s Manual Supplementary Documents: 12 — 13
B. W. Kernighan and P. J. Plauger: 『Software Tools in Pascal』、Addison-Wesley、1981年。