sed の動作をより詳しく見ていきましょう.sed は次のような手順で処理を行います.
- ファイルから 1 行データを読み込み,パターンスペースと呼ばれる記憶領域に保存する
- パターンスペースに保存されているデータに対し,置換などの指定された処理を行う
- パターンスペースに残っているデータを画面に出力し,パターンスペースを空にする
この手順を,前節 26.3.1 sed とは? の例で確認してみます.ターミナルで
sed "s/[0-9][0-9]/'/" nobelprize.txt

と入力すると
- sed は nobelprize.txt の 1 行目
2011 Saul Perlmutter, Brian P. Schmidt, Adam G. Riess
を読み込み,パターンスペースに格納します.
- sed は指定したスクリプト s/[0-9][0-9]/’/ をパターンスペースに格納した文字列に対して実行します.今の場合,パターンスペースに読み込まれている 2011 の最初の 2 桁が [0-9][0-9] にマッチし,アポストロフィ ‘ に置換されます.
- パターンスペースには,置換された後の文字列
'11 Saul Perlmutter, Brian P. Schmidt, Adam G. Riess
が格納されています.これが画面に出力されます.
- パターンスペースの内容が消去され,sed は 2 行目
2010 Andre Geim, Konstantin Novoselov
をパターンスペースに読み込みます.この後の操作は全く同様で,sed が nobelprize.txt の最終行を読み込むまで同じ操作が繰り返されます.
こうしてテキスト全体に対する置換が実現されていたのです.いまの場合 sed はパターンスペースに対して置換を行いましたが,sed の引数に与える命令を変えると,違う操作もできるようになります.その例として,sed を grep と同じように使ってみます.次のように入力することで,26.2.1 grep とは? やったように “Paul” という文字列を含む行を表示させることができます.なお,シェルによってはエラーメッセージが出ることがあります.そのときはクォーテーションをダブル ” ではなくシングル ‘ にしてみてください.
sed "/Paul/!d" nobelprize.txt
1989 Norman F. Ramsey, Hans G. Dehmelt, Wolfgang Paul
1963 Eugene Paul Wigner, Maria Goeppert Mayer, J. Hans D. Jensen
1945 Wolfgang Pauli
1933 Erwin Schrödinger, Paul Adrien Maurice Dirac
このコマンドの動作を 1 ステップずつ追いかけてみましょう.
- sed は nobelprize.txt の 1 行目をパターンスペースに読み込みます.
- /Paul/ は「”Paul” を含む行」を意味します.その後ろに感嘆符 ! をつけて /Paul/! とすると「”Paul” を含まない行」という意味になります.nobelprize.txt の 1 行目に “Paul” は含まれていないので,/Paul/! は 1 行目にマッチします.
- マッチしたので d コマンドが実行されます.d は delete の d で,パターンスペース内のデータを全部消すコマンドです.したがってパターンスペースは空になります.
- 本来ならスクリプト処理の後にパターンスペース内の文字列が表示されますが,今はパターンスペースが空っぽなので,何も表示されません.引き続き nobelprize.txt の 2 行目が読み込まれ,同じ手順が繰り返されます.
- しばらく何も表示されない状態が続きますが,1989 年の行に来ると “Wolfgang Paul” にマッチします.よってこの行では d コマンドが実行されません.
- パターンスペースに格納されている
1989 Norman F. Ramsey, Hans G. Dehmelt, Wolfgang Paul
が表示されます.この後パターンスペースがクリアされ,次の 1988 年の行が読み込まれます.以下同様にして,上の出力結果が得られます.
この動作は
sed -n "/Paul/p" nobelprize.txt

としても実現できます.こうすると sed の動作は次のようになり,動作の仕方は違うものの出力結果は sed “/Paul/!d” nobelprize.txt と同じになります.
- p コマンドはパターンスペースに保存されているデータを出力されているコマンドです.よって “Paul” がマッチした行は p コマンドで画面に出力されます.
- sed のオプション -n は,次の行を読み込む前にパターンスペース内のデータを出力させないようにする命令です.よって p コマンドで出力されない限り,画面には何も表示されません.
このように sed では,置換以外にも様々な手法で出力を制御することができます.次節では sed の出力をより細かく制御するため,sed の文法を詳しく説明します.
