6.4.1 分岐とサイクル

b、t、Tコマンドの後にはラベルを指定できます(通常は1つの字母です)。ラベルは、コロンの後に1つ以上の字母を続けて定義します(たとえば「:x」)。ラベルを省略した場合、分岐コマンドはサイクルを再開します。ラベルへの分岐とサイクルの再開の違いに注意してください。サイクルを再開すると、sedはまずパターンスペースの現在の内容を表示し、その後、次の入力行をパターンスペースへ読み込みます。ラベルへ移動する場合は、たとえそのラベルがプログラムの先頭にあっても、パターンスペースを表示せず、次の入力行も読み込みません。

次のプログラムは何も変更しません。プログラム中の唯一のコマンドであるbコマンドにはラベルがないため、単にサイクルを再開します。各サイクルで、パターンスペースを表示し、次の入力行を読み込みます。

$ seq 3 | sed b
1
2
3

次の例は無限ループです。終了せず、何も表示しません。bコマンドは「x」ラベルへ移動し、新しいサイクルは開始されません。

$ seq 3 | sed ':x ; bx'

# The above command requires gnu sed (which supports additional
# commands following a label, without a newline). A portable equivalent:
#     sed -e ':x' -e bx

分岐は、nやNコマンドと組み合わせることがよくあります。どちらも、サイクルの再開を待たずに次の入力行をパターンスペースへ読み込みます。次の入力行を読む前に、nは現在のパターンスペースを表示してから空にします。一方、Nは改行と次の入力行をパターンスペースへ追加します。

次の2つの例を考えてみます。

$ seq 3 | sed ':x ; n ; bx'
1
2
3

$ seq 3 | sed ':x ; N ; bx'
1
2
3
  • どちらの例も、新しいサイクルを開始しないにもかかわらず、無限ループにはなりません。
  • 最初の例では、nコマンドがまずパターンスペースの内容を表示し、パターンスペースを空にしてから、次の入力行を読み込みます。
  • 2つ目の例では、Nコマンドが次の入力行を改行付きでパターンスペースへ追加します。読み込む入力行がなくなるまでパターンスペースに行を蓄積し、その後、Nコマンドがsedプログラムを終了します。プログラムの終了時にはサイクル末尾の処理を行い、パターンスペース全体を表示します。
  • 2つ目の例では、NのPOSIX標準にない動作を使うため、GNU sedが必要です。バグの報告にある「最後の行でのNコマンド」の段落を参照してください。
  • 2つの例の違いをさらに調べるには、次のコマンドを試してください。
    printf '%s\n' aa bb cc dd | sed ':x ; n ; = ; bx'
    printf '%s\n' aa bb cc dd | sed ':x ; N ; = ; bx'
    printf '%s\n' aa bb cc dd | sed ':x ; n ; s/\n/***/ ; bx'
    printf '%s\n' aa bb cc dd | sed ':x ; N ; s/\n/***/ ; bx'