特定のパターンの最後の出現から別のパターンの最初の出現までの範囲を印刷します

特定のパターンの最後の出現から別のパターンの最初の出現までの範囲を印刷します

おはようございます。これは質問に非常に似ていますパターンの最後の出現から別のパターンまでの grep(数か月前のもの)に、もう少し詳細を追加しました。

複数の重複パターンと、それに続く探しているパターンを含むファイル用の UNIX スクリプトを作成しようとしています。ただし、'tac' または 'tail -r' (UNIX エミュレーター、MKS Toolkit を使用) がないため、パターン 2 の前のパターン 1 の最後の出現を返し、その後にパターン 1 とパターン 2 の間のデータ、さらにパターン 2 も返したいと考えています。この場合のパターンは、'条件 1' と '条件 2' になります。

出力:

...
Condition 1: A
data1
Condition 1: B
data2
Condition 2: C
data3
Condition 1: D
data4
Condition 1: E
data5
Condition 2: F
...

次を返す awk (または sed、ただし awk が適切なツールだと考えました) スクリプトを書きたいと思います。

Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

これは以下の行の何らかの形式であると思われますが、構文がわかりません。

awk '/Condition 1/ {acc = $0;} /,/Condition 2/ {print ?}' output.out

'/,/' の操作で問題が発生しているようです。どなたかアドバイスをいただけたら幸いです。この質問に関するご助力とご協力に感謝いたします。

答え1

試す:

$ awk 'f{a=a"\n"$0} /Condition 1/{a=$0; f=1} f && /Condition 2/{print a; f=0}' output.out 
Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

使い方

  • f{a=a"\n"$0}

    変数fが true (ゼロ以外) の場合、現在の行を変数の末尾に追加しますa

  • /Condition 1/{a=$0; f=1}

    現在の行に が含まれている場合はCondition 1、 をs現在の行に設定し、変数をf1 に設定します。

  • f && /Condition 2/{print a; f=0}

    fが真で、現在の行に が含まれている場合はCondition 2、変数を印刷しafゼロに戻します。

答え2

テキスト処理で逆アドレス指定をしたい場合は、ex

そのPOSIX指定vi、これは(およびviの直前の版)のスクリプト化可能な形式であり、非常に柔軟です。

printf '%s\n' 'g/Condition 2/?Condition 1?,.p' | ex output.out

これはつまり:

パターン「条件 2」に一致するすべての行(g全体的に)について、「条件 1」の直前のインスタンスを逆方向に検索し、その行から現在の行( )(「条件 2」が含まれている行)までpのすべての行を印刷します。.

提供された入力に対する出力は、まさにあなたが説明したとおりです。

答え3

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x' infile

ただし、これは一致する行PATTERN_2の前に少なくとも 1 つの一致する行があることを前提としていますPATTERN_1。より一般的なケースでは、印刷前にパターン スペースに存在するかどうかをテストする別の条件を追加しますPATTERN_1

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x;/PATTERN_1/!d' infile

答え4

ここに、Perl の悪質な部分があります:

perl -0777 -ne '
    my $c1 = qr/Condition 1/;
    my $c2 = qr/Condition 2/;
    print for map {s/$c2.*?\n\K.*//s; $_}
              grep {/$c2/}
              split /(?=$c1)/ms;
' output.out

それ:

  • ファイル全体を読み取ります(-0777および-nオプションを使用)。
  • 条件1が現れるところで分割します(split)、
  • 条件2が出現しない段落を除外する(grep)、
  • 次に、各興味深い段落から条件 2 の行 ( map) に続く行を削除します。

関連情報