ファイルから次の文字列をどのように抽出できますか?

ファイルから次の文字列をどのように抽出できますか?

次のデータを考慮してください(file.txtにあると仮定)。

P 5 24 0 0 -9.0786328019999996e+02 9.1141809916739828e+02 8.0419002445999993e+01 22 0 0 -6 0
P 8 24 -3.9196518724924090e+00 2.0727804903086735e+00 -8.9632605571651516e+02 8.9993737237679568e+02 8.0419002445999993e+01 44 0 0 -65 0
P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
E 2 -1 -1.0000000000000000e+00 XXX
P 5 24 0 0 -6.7702324192000003e+02 6.8178272642703166e+02 8.0419002445999993e+01 22 0 0 -6 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0
E 3 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 YY

すなわち、一般に次のような形態を有する。

P ..
...
P ..
E ..
P ..
...
P ..
E ..

P ..前の行だけを含むファイルを作成できるかどうか教えてくださいE ..

つまり、ファイルと

P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0

答え1

使用grep(次のように表示したため-B)、私たちが使用するツールの実装には、一致する行といくつかの以前の行を抽出するための非標準オプションがあると仮定します。

$ grep -B 1 '^E' file.txt | grep '^P'
P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0

これは2回使用されますgrep。まず、その行で始まるすべての行とその行の前のすべての行を抽出し、次にその行で始まる行を抽出しEますP

その結果で始まる行が表示され、P直後に始まる行が表示されますE

2番目の出力をgrepファイルにリダイレクトして、いくつかのファイルに保存します。


変数で始まる行を使用して記憶しawk、表示したときに始まる行を印刷して消去します。PplineE

$ awk '/^P/ { pline = $0 } /^E/ && length(pline) > 0 { print pline; pline = "" }' file
P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0

行が2つ以上の連続行グループではなく、個別にのみ発生することを前提として使用しますsed(そうであれば、E最新の行出力は1行に1回表示されます).PE

$ sed -e '/^P/ { h; d; }' -e 'g'  file
P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0

これにより、Pすべての行が予約済みスペースに保存され、次のループがすぐに開始されます。行が行でない場合は、予約済みスペースから最後Pに保存された行を取得して出力します。P

(同じ仮定に基づいてawk上記のコードを減らしてawk '/^P/ { pline = $0; next } { print pline }' file文字通りに翻訳することができますsedawk

関連情報