
おはようございます。これは質問に非常に似ていますパターンの最後の出現から別のパターンまでの 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
現在の行に設定し、変数をf
1 に設定します。f && /Condition 2/{print a; f=0}
f
が真で、現在の行に が含まれている場合はCondition 2
、変数を印刷しa
、f
ゼロに戻します。
答え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
) に続く行を削除します。