注文する:

注文する:

ブロックは常に00 PROGRAMで始まります。

XYZで終わり、その後に空行が続きます。 XYZは前の行ブロックにも表示されますが、前の行の後にはより多くのデータが続きます。空行の前の最後の行だけが必要です。私の意図に一致するコードが見つかりませんでした。これが誰かに簡単な答えであることを願っています!

空行の前の最後の行を維持したいです。たとえば、

000-12-22
AB1
00   PROGRAM
01   INQUIRY
03   XYZ
04   XYZ
blank line
LINE VALUE
00456

この部分だけを削除するだけです。

00   PROGRAM
01   INQUIRY
03   XYZ

答え1

このタイプの範囲は次のとおりです。完璧ユースケースex 私は持っていますexたくさん書いたこのサイトはスクリプトファイルを編集するための最高のPOSIXツールです。

注文する:

1 つのブロックのみを処理する必要がある場合は、次を使用してください。

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt

複数のブロックが可能な場合は、以下を使用してください。

printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' x | ex file.txt

テストするには、%p次を代わりに使用してくださいx

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' %p | ex file.txt
printf '%s\n' 'g/00 PROGRAM/.,/^$/-2d' %p | ex file.txt

これにより、バッファの内容をファイルに再保存するのではなく、バッファ全体が印刷されます。


イラスト:

[vagrant@localhost ~]$ cat file.txt 
000-12-22
AB1
00 PROGRAM
01 INQUIRY
03 XYZ
04 XYZ

LINE VALUE
00456
[vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt 
[vagrant@localhost ~]$ cat file.txt 
000-12-22
AB1
04 XYZ

LINE VALUE
00456
[vagrant@localhost ~]$ 

説明とコメント:

を使用できますが、ex -c 'editingcommands' filenameこれが解決するよりも多くの問題を引き起こすことがわかりました。exエラーが発生した場合、終了するのではなくユーザー入力を待って停止します。さらにex、POSIXはこれを行うことができる共通の機能を保証しないため、この方法で複数のコマンドを渡すことに潜在的な移植性の問題があります。

代わりに、通常はコマンドをexfromにパイプしますprintf。これにより、複数のコマンドをフォーマット文字列を使用して%s\n簡単に改行で区切るprintfことができます。エラーが発生した場合(ファイルの最後の行よりも大きい行を編集しようとする場合)、ファイルは中断されずに残ります。

実際にファイルを編集する前に、コマンドをテストするために%p最後のコマンドとして(フルバッファ印刷)を使用します。その後、コマンドを少し調整し、必要な正確なファイル内容が得られるまで繰り返し実行できます。結果に満足したら、コマンドを実行するように%p変更します。x一つ実際、ファイルの変更を保存するのに時間がかかります。

この質問に対する答えとして私が下したコマンドは次のとおりです。

printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x | ex file.txt

このコマンドは、次のように新しい行で区切られたprintf3つの文字列を印刷します。/00 PROGRAM/.,/^$/-2dx

[vagrant@localhost ~]$ printf '%s\n' '/00 PROGRAM/' '.,/^$/-2d' x
/00 PROGRAM/
.,/^$/-2d
x
[vagrant@localhost ~]$ 

これらの3行はexコマンドです。

exコマンドの概要

コマンドは、exアドレス(ラインベース)とコマンドの2つの部分で構成されています。

アドレスが1つしかない場合、カーソルはそのアドレス(対応する行に移動)に移動します。

コマンドのみがある場合、現在の行がアドレスとして使用されます。

住所は通常範囲— 住所、カンマ、その他の住所順です。最初のアドレスから2番目のアドレスまでのすべての行を表します。

アドレスは行番号にすることができますが、必ずしもそうではありません。 「この正規表現に一致する現在の行の次の行」を意味する検索パターンでもあります。前方に検索することも、後方に検索することもできます。

foo「このインスタンスの前の2行は、現在の行の直前のインスタンスの後に発生します」というアドレスを書き込むこともできます。barこれは次のとおりです。?bar?/foo/-2

段階的に

コマンド/00 PROGRAM/は単なるアドレスなので、「パターン「00 PROGRAM」の最初のインスタンスにカーソルを移動してください」という意味です。

このコマンドは.,/^$/-2d2つの部分で構成されています。最後はd「削除」を意味するコマンドです。今残ったのは住所だけだ。

最初の文字.は現在の行を表す特別なアドレスです。

パターンは空行(行の先頭と行の終わり)/^$/の正規表現です。この場合、現在のカーソル位置の後の空行を意味します。^$

-2これは「2行後ろ」を意味します。

さて、これが.,/^$/-2d意味するのは、「現在の行から次の空白行の上の2行まで行を削除します」です。

x簡単に言えば、バッファの内容をファイルに保存してエディタを終了します。


これがあなたに役立つことを願っています。 ex非常に強力なテキスト編集ツールです。vi「ビジュアルエディタ」の全身です。すべてのコマンドをex実行することもできます。vi

答え2

修正された質問に答えてください

このテストファイルを考えてみましょう。

$ cat File2
000-12-22
AB1
00 PROGRAM
01 INQUIRY
03 XYZ
04 XYZ

LINE VALUE
00456

次のコマンドを試してください。

$ sed '/00 PROGRAM/,/^$/{/./{h;d}; x; p; x;}' File2
000-12-22
AB1
04 XYZ

LINE VA

ルーエ00456

元の質問に答える

00 PROGRAM私が正しく理解した場合は、空の行を含む行で始まり、終わる複数の前払いセットを含むファイルがありますXYZ。この場合は、以下を試してください。

sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 

はい

次のサンプルファイルを考えてみましょう。

$ cat file
00 PROGRAM
some
XYZ discard this
data
XYZ keep this

other
00 PROGRAM
more
XYZ keep this also

end

これはXYZブロックの空白行の前の行だけを保持します00 PROGRAM

$ sed -n '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/p}' file 
XYZ keep this
XYZ keep this also

選ぶ

おそらく、グループ外のすべての行を維持し、一致する場合は、グループの最後の空でない行も維持したいと思うでしょうXYZ。この場合:

$ sed '/00 PROGRAM/,/^$/{/./{h;d}; x;/XYZ/!d}' file 
XYZ keep this
other
XYZ keep this also
end

関連情報