おはようございます。質問によく似ています。最後のパターン発生から別のパターンへのGrep(数ヶ月前)詳細を追加しながら。
私は複数の繰り返しパターンがあり、その後に私が見つけたいパターンがあるファイルのUNIXスクリプトを書こうとしています。ただし、「tac」または「tail -r」(UNIXエミュレータMKS Toolkitを使用)がなく、Pattern2より前に最後に発生したPattern1を返し、Pattern1とPattern2の間のデータを返し、もう一度Pattern2を返そうとします。この例のパターンは「条件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(0ではない)の場合、現在の行は変数の末尾に追加されますa
。/Condition 1/{a=$0; f=1}
現在の行にが含まれている場合は、現在の行に
Condition 1
設定し、変数を1に設定します。s
f
f && /Condition 2/{print a; f=0}
f
trueで、現在の行にが含まれている場合、Condition 2
変数は印刷され、再び0にa
設定されます。f
答え2
テキスト処理でリバースアドレッシングが必要な場合は、次のようにします。ex
それPOSIXの指定vi
、これは(およびvi
その直前の)スクリプト可能な形式で非常に柔軟です。
printf '%s\n' 'g/Condition 2/?Condition 1?,.p' | ex output.out
これは次のことを意味します。
「condition2」パターンに一致する各行(グローバル)に対して、g
「condition1」の前のインスタンスを後ろに検索し、その行から現在の行(「condition2」がある行など)までのすべての行を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
)、 grep
条件 2( ) に現れない段落をフィルタリングし、- 次に、関心のある各段落から条件付き2行()の後の
map
すべての行を削除します。