103

sedの2つの概念であるホールドスペースとパターンスペースに混乱しています。誰かがそれらを説明するのを手伝ってもらえますか?

マニュアルの抜粋は次のとおりです。

h H    Copy/append pattern space to hold space.
g G    Copy/append hold space to pattern space.

n N    Read/append the next line of input into the pattern space.

これらの6つのコマンドは本当に私を混乱させます。

4

3 に答える 3

132

sedがファイルを1行ずつ読み取る場合、現在読み取られている行がパターンバッファー(パターンスペース)に挿入されます。パターンバッファは、現在の情報が保存されるスクラッチパッドである一時バッファのようなものです。sedに印刷するように指示すると、パターンバッファが印刷されます。

ホールドバッファ/ホールドスペースは長期保存のようなもので、何かをキャッチして保存し、後でsedが別の行を処理しているときに再利用できます。ホールドスペースを直接処理するのではなく、何かを実行したい場合は、ホールドスペースをコピーするか、パターンスペースに追加する必要があります。たとえば、printコマンドpは、パターンスペースのみを印刷します。同様にs、パターン空間で動作します。

次に例を示します。

sed -n '1!G;h;$p'

(-nオプションは、行の自動印刷を抑制します)

ここには、、、およびの3つのコマンドが1!Gありhます$p1!Gアドレス1(最初の行)がありますが、コマンド!最初の行以外のすべての場所で実行されることを意味します。一方、最後の行でのみ実行されます。だから何が起こるかこれは:$p

  1. 最初の行が読み取られ、パターンスペースに自動的に挿入されます
  2. 最初の行では、最初のコマンドは実行されません。最初の行を保留スペースhにコピーします。
  3. これで、2行目がパターンスペースにあったものを置き換えます
  4. 2行目では、最初に実行しG、ホールドバッファの内容をパターンバッファに追加し、改行で区切ります。パターンスペースには、2行目、改行、および1行目が含まれています。
  5. 次に、hコマンドはパターンバッファの連結された内容をホールドスペースに挿入します。ホールドスペースは、反転した2行目と1行目を保持します。
  6. 3行目に進みます-上記のポイント(3)に進みます。

最後に、最後の行が読み取られ、ホールドスペース(前のすべての行が逆の順序で含まれている)がパターンスペースに追加された後、パターンスペースは。で印刷されpます。ご想像のとおり、上記はtacコマンドが実行することを正確に実行します-ファイルを逆に出力します。

于 2012-10-11T07:30:21.870 に答える
21

@エドモートン:私はここであなたに同意しません。sedマルチライングレッピングを行うためのエレガントな方法を思い付くのに、非常に便利でシンプルであることがわかりました(パターンの概念を理解し、バッファーを保持すると)。

たとえば、ホスト名と各ホストに関する情報が含まれているテキストファイルを見てみましょう。その間に、私が気にしない多くのがらくたがあります。

Host: foo1
some junk, doesnt matter
some junk, doesnt matter
Info: about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Info: a second line about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Host: foo2
some junk, doesnt matter
Info: about foo2 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter

私にとって、ホスト名と対応するinfo行を含む行を取得するawkスクリプトは、sedで実行できるものよりも少し時間がかかります。

sed -n '/Host:/{h}; /Info/{x;p;x;p;}' myfile.txt

出力は次のようになります。

Host: foo1
Info: about foo1 that I really care about!!
Host: foo1
Info: a second line about foo1 that I really care about!!
Host: foo2
Info: about foo2 that I really care about!!

Host: foo1これは出力に2回表示されることに注意してください。)

説明:

  1. -n明示的に印刷されない限り、出力を無効にします
  2. 最初に一致し、行を見つけHost:てホールドバッファに入れます(h)
  3. 2番目の一致は、次のInfo:行を検索しますが、最初にパターンバッファー内の現在の行をホールドバッファーと交換(x)し、そのHost:行を印刷(p)してから、再交換(x)してInfo:行を印刷(p)します。

はい、これは単純な例ですが、これは単純なsedワンライナーですぐに対処された一般的な問題だと思います。特定の予測可能なシーケンスに依存できないタスクなど、はるかに複雑なタスクの場合は、awkの方が適している場合があります。

于 2013-08-19T19:30:15.833 に答える
18

@ Januaryの答えと例は素晴らしいですが、説明は私には十分ではありませんでした。正確にどのように機能するかを理解するまで、私は多くのことを検索して学ぶ必要がありましたsed -n '1!G;h;$p'。それで、私のような誰かのためのコマンドについて詳しく説明したいと思います。

まず、コマンドの機能を見てみましょう。

$ echo {a..d} | tr ' ' '\n' # Prints from 'a' to 'd' in each line
a
b
c
d
$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;$p'
d
c
b
a

コマンドと同じように入力を逆にしますtac

sed行ごとに読み取るので、各行のパッテンスペースホールドスペースで何が起こるかを見てみましょう。コマンドがパターンスペースの内容をホールドスペースにコピーするのでh、両方のスペースは同じテキストを持ちます。

Read line    Pattern Space / Hold Space    Command executed
-----------------------------------------------------------
a            a$                            h
b            b\na$                         1!G;h
c            c\nb\na$                      1!G;h
d            d\nc\nb\na$                   1!G;h;$p

最後の行で、次のようにフォーマットされた$pプリントd\nc\nb\na$

d
c
b
a

各行のパターンスペースを確認したい場合は、lコマンドを追加できます。

$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;l;$p'
a$
b\na$
c\nb\na$
d\nc\nb\na$
d
c
b
a

このビデオチュートリアルを見ると、 sedがどのように機能するかを理解するのに非常に役立ちました。男は、各スペースがどのように使用されるかを段階的に示しています。ホールドスペースは第4チュートリアルで参照されていますが、に慣れていない場合は、すべてのビデオを視聴することをお勧めしsedます。

また、 GNUsedドキュメントBruceBarnettのSedチュートリアルは非常に優れたリファレンスです。

于 2017-06-05T19:54:30.420 に答える