sed簡単整理2 - パターンスペース・ホールドスペース -

パターンスペース及びホールドスペースに関してのメモです。

パターンスペース

下記のコマンドを

sed -e 's/hoge/Hoge/; s/foo/Foo/' sed_test.txt

疑似コードに変えると、下記のような感じになります(100%同じではないと思いますが)。

while (input.next()) {
    patternSpace = input.readLine()
    patternSpace = patternSpace.replace("hoge", "Hoge")
    patternSpace = patternSpace.replace("foo", "Foo")
    result.append(patternSpace)
}

つまり、パターンスペースは読み込んだ行そのものでありながら、コマンドの実行結果を保存する領域だといえます。

整理すると、通常のsedの処理を疑似コードに移すなら、以下のようになると思います。

while (input.next()) {
    行を読み込んでパターンスペースに入れる。

    直前のパターンスペースの内容に対し、コマンド1を実行し、パターンスペースに入れる。
    ...
    直前のパターンスペースの内容に対し、コマンドxを実行し、パターンスペースに入れる。

    直前のパターンスペースの内容を出力する。
}

コマンド1・・・コマンドxと書きましたが、セミコロン(;)で複数のコマンドが指定されたことを表します。

行 > パターンスペース > 処理 > ... > パターンスペース > 処理 > 結果の順ですね。

ホールドスペース

まず、下記はホールドスペースを使用した例と結果です。

cat << EOF > sed_test.txt
a apple haha
b apple hihi
c apple hopi
d man ama
EOF

sed -e 'G;h' sed_test.txt
#a apple haha
#
#b apple hihi
#a apple haha
#
#c apple hopi
#b apple hihi
#a apple haha
#
#d man ama
#c apple hopi
#b apple hihi
#a apple haha
#

上記のsedコマンドを疑似コードに変えると、下記のような感じになります(あくまで感じですが..)。

while (input.next()) {
    patternSpace = input.readLine();
    // Gコマンド
    patternSpace = patternSpace + "\n" + (holdSpace.isEmpty() ? "" : holdSpace)
    // hコマンド
    holdSpace = patternSpace
    patternSpace = patternSpace + "\n"
    print(patternSpace)
}

疑似コードを見ると分かると思いますが、ホールドスペースはパータンスペースの内容をコピーして保管したり、戻したりする領域です。
これでもっと複雑な文字列操作が行えます。

疑似コード的には次のようになったと考えればいいかなと思います。

while (input.next()) {
    行を読み込んでパターンスペースに入れる。

    直前のパターンスペースの内容に対し、コマンド1を実行し、パターンスペースに入れる。
    ...
    [パターンスペースの内容をホールドスペースにコピーしたり逆に戻したりする]
    ...
    直前のパターンスペースの内容に対し、コマンドxを実行し、パターンスペースに入れる。

    直前のパターンスペースの内容を出力する。
}

下記はsedの主なホールドスペース操作に必要なコマンドです。大文字は追記で、小文字は破棄してから追記です。

  • g : ホールドスペース -> パターンスペースにコピーします。パターンスペースにあった既存の内容は破棄されます。
  • G : ホールドスペース -> パターンスペースに追記します(次の行として追加)。
  • h : パターンスペース -> ホールドスペースにコピーします。ホールドスペースにあった既存の内容は破棄されます。
  • H : パターンスペース -> ホールドスペースに追記します(次の行として追加)。
  • d : パターンスペースを削除します。
  • D : パターンスペースの1行目を削除します。

他のコマンドと同じく"アドレス+コマンド+コマンドパラメータ"の形式で指定します。

次回はループ・bコマンドについて整理してみます。