GNU/Linux >> Linux の 問題 >  >> Linux

sedにおける「ホールド空間」と「パターン空間」の概念

@Ed Morton:私はあなたに同意しません。 sed を見つけました 非常に便利でシンプル (パターンとホールド バッファーの概念を理解すれば)、複数行の grep を行うエレガントな方法を考え出すことができます。

たとえば、ホスト名と各ホストに関するいくつかの情報を含むテキスト ファイルを取り上げてみましょう。その間には、私は気にしませんがたくさんのジャンクがあります。

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 回表示されます。)

説明:

<オール>
  • -n 明示的に印刷しない限り、出力を無効にします
  • 最初に一致した Host: を見つけて配置します ホールド バッファへの行 (h)
  • 2 番目に一致し、次の Info:行を見つけますが、最初に (x) パターン バッファー内の現在の行をホールド バッファーと交換し、(p) Host: を出力します。 行を再交換 (x) し、Info:行を出力 (p) します。
  • はい、これは単純な例ですが、単純な sed ワンライナーですぐに対処できる一般的な問題だと思います。与えられた予測可能なシーケンスに依存できないタスクなど、はるかに複雑なタスクには、awk が適している場合があります。


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

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

    以下に例を示します:

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

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

    ここには 3 つのコマンドがあります:1!Gh$p . 1!G アドレス 1 を持っています (最初の行)、しかし ! ただしどこでもコマンドが実行されることを意味します 最初の行に。 $p 一方、最後の行でのみ実行されます。すると、次のようになります:

    <オール>
  • 最初の行が読み取られ、パターン スペースに自動的に挿入されます
  • 最初の行では、最初のコマンドは実行されません。 h 最初の行を hold にコピーします スペース。
  • 2 行目は、パターン スペースにあったものを置き換えます
  • 2 行目では、まず G を実行します。 ホールド バッファの内容をパターン バッファに追加し、改行で区切ります。パターン スペースには、2 行目、改行、1 行目が含まれるようになりました。
  • では、h コマンドは、パターン バッファの連結された内容をホールド スペースに挿入します。ホールド スペースには、反転した行 2 と 1 が保持されます。
  • 行番号 3 に進みます -- 上記のポイント (3) に進みます。
  • 最後に、最後の行が読み取られ、ホールド スペース (前のすべての行を逆の順序で含む) がパターン スペースに追加された後、パターン スペースは p で出力されます。 .ご想像のとおり、上記は tac とまったく同じことを行います コマンドは -- ファイルを逆に印刷します。


    @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の仕組みを理解するのに非常に役立ちました。 hold spaced は 4 番目のチュートリアルで参照されていますが、sed に慣れていない場合は、すべてのビデオを視聴することをお勧めします。 .

    また、GNU sed ドキュメントと Bruce Barnett の Sed チュートリアルも非常に参考になります。


    Linux
    1. Linuxsedコマンドの使用方法

    2. Linux Sedコマンド:使用法と例

    3. コマンドラインでXキーとポインターグラブを操作しますか?

    1. ファイルの最初の行の前にテキストを挿入する方法は?

    2. 一致する行と一致する行からN番目の行を印刷しますか?

    3. Sedを使用してパターンマッチ後に前の行を印刷しますか?

    1. sedを使用してコマンドラインでテキストを操作する

    2. カスタム正規表現区切り文字を使用してパターンを含む行番号を見つけますか?

    3. OdとHexdumpのデフォルトの行の長さを変更するにはどうすればよいですか?